this repo has no description
at develop 91 kB view raw
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2 3/* 4 * Main authors: 5 * Guido Tack <guido.tack@monash.edu> 6 */ 7 8/* This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 11 12#include <minizinc/astexception.hh> 13#include <minizinc/astiterator.hh> 14#include <minizinc/flatten_internal.hh> 15#include <minizinc/hash.hh> 16#include <minizinc/prettyprinter.hh> 17#include <minizinc/typecheck.hh> 18 19#include <sstream> 20#include <string> 21#include <unordered_map> 22 23namespace MiniZinc { 24 25Scopes::Scopes(void) { 26 s.push_back(Scope()); 27 s.back().toplevel = true; 28} 29 30void Scopes::add(EnvI& env, VarDecl* vd) { 31 if (!s.back().toplevel && vd->ti()->isEnum() && vd->e()) { 32 throw TypeError(env, vd->loc(), "enums are only allowed at top level"); 33 } 34 if (vd->id()->idn() == -1 && vd->id()->v() == "") return; 35 DeclMap::iterator vdi = s.back().m.find(vd->id()); 36 if (vdi == s.back().m.end()) { 37 s.back().m.insert(vd->id(), vd); 38 } else { 39 GCLock lock; 40 throw TypeError(env, vd->loc(), "identifier `" + vd->id()->str().str() + "' already defined"); 41 } 42} 43 44void Scopes::push(bool toplevel) { 45 s.push_back(Scope()); 46 s.back().toplevel = toplevel; 47} 48 49void Scopes::pop(void) { s.pop_back(); } 50 51VarDecl* Scopes::find(Id* ident) { 52 int cur = static_cast<int>(s.size()) - 1; 53 for (;;) { 54 DeclMap::iterator vdi = s[cur].m.find(ident); 55 if (vdi == s[cur].m.end()) { 56 if (s[cur].toplevel) { 57 if (cur > 0) 58 cur = 0; 59 else 60 return NULL; 61 } else { 62 cur--; 63 } 64 } else { 65 return vdi->second; 66 } 67 } 68} 69 70struct VarDeclCmp { 71 std::unordered_map<VarDecl*, int>& _pos; 72 VarDeclCmp(std::unordered_map<VarDecl*, int>& pos) : _pos(pos) {} 73 bool operator()(Expression* e0, Expression* e1) { 74 if (VarDecl* vd0 = Expression::dyn_cast<VarDecl>(e0)) { 75 if (VarDecl* vd1 = Expression::dyn_cast<VarDecl>(e1)) { 76 return _pos[vd0] < _pos[vd1]; 77 } else { 78 return true; 79 } 80 } else { 81 return false; 82 } 83 } 84}; 85struct ItemCmp { 86 std::unordered_map<VarDecl*, int>& _pos; 87 ItemCmp(std::unordered_map<VarDecl*, int>& pos) : _pos(pos) {} 88 bool operator()(Item* i0, Item* i1) { 89 if (VarDeclI* vd0 = i0->cast<VarDeclI>()) { 90 if (VarDeclI* vd1 = i1->cast<VarDeclI>()) { 91 return _pos[vd0->e()] < _pos[vd1->e()]; 92 } else { 93 return true; 94 } 95 } else { 96 return false; 97 } 98 } 99}; 100 101std::string createEnumToStringName(Id* ident, std::string prefix) { 102 std::string name = ident->str().str(); 103 if (name[0] == '\'') { 104 name = "'" + prefix + name.substr(1); 105 } else { 106 name = prefix + name; 107 } 108 return name; 109} 110 111AssignI* createEnumMapper(EnvI& env, Model* m, unsigned int enumId, VarDecl* vd, 112 VarDecl* vd_enumToString, Model* enumItems) { 113 Id* ident = vd->id(); 114 SetLit* sl = vd->e()->dyn_cast<SetLit>(); 115 ArrayLit* enum_init_al = NULL; 116 AssignI* ret = NULL; 117 118 GCLock lock; 119 if (ArrayLit* al = vd->e()->dyn_cast<ArrayLit>()) { 120 enum_init_al = al; 121 } else if (Call* c = vd->e()->dyn_cast<Call>()) { 122 if (c->id() != "anon_enum") { 123 throw TypeError(env, c->loc(), "invalid initialisation for enum `" + ident->v().str() + "'"); 124 } 125 if (c->n_args() == 1 && c->arg(0)->isa<ArrayLit>()) { 126 enum_init_al = c->arg(0)->cast<ArrayLit>(); 127 } 128 } 129 if (enum_init_al) { 130 std::vector<Expression*> enumIds(enum_init_al->size()); 131 for (unsigned int i = 0; i < enum_init_al->size(); i++) { 132 if (Id* eid = (*enum_init_al)[i]->dyn_cast<Id>()) { 133 enumIds[i] = eid; 134 } else { 135 throw TypeError(env, vd->e()->loc(), 136 "invalid initialisation for enum `" + ident->v().str() + "'"); 137 } 138 } 139 sl = new SetLit(vd->e()->loc(), enumIds); 140 } 141 if (sl) { 142 for (unsigned int i = 0; i < sl->v().size(); i++) { 143 if (!sl->v()[i]->isa<Id>()) { 144 throw TypeError(env, sl->v()[i]->loc(), 145 "invalid initialisation for enum `" + ident->v().str() + "'"); 146 } 147 TypeInst* ti_id = new TypeInst(sl->v()[i]->loc(), Type::parenum(enumId)); 148 149 std::vector<Expression*> toEnumArgs(2); 150 toEnumArgs[0] = vd->id(); 151 toEnumArgs[1] = IntLit::a(i + 1); 152 Call* toEnum = new Call(sl->v()[i]->loc(), ASTString("to_enum"), toEnumArgs); 153 toEnum->decl(env.model->matchFn(env, toEnum, false)); 154 VarDecl* vd_id = new VarDecl(ti_id->loc(), ti_id, sl->v()[i]->cast<Id>()->str(), toEnum); 155 enumItems->addItem(new VarDeclI(vd_id->loc(), vd_id)); 156 } 157 SetLit* nsl = new SetLit(vd->loc(), IntSetVal::a(1, sl->v().size())); 158 Type tt = nsl->type(); 159 tt.enumId(vd->type().enumId()); 160 nsl->type(tt); 161 vd->e(nsl); 162 } else if (!vd->e()->isa<Call>()) { 163 throw TypeError(env, vd->e()->loc(), 164 "invalid initialisation for enum `" + ident->v().str() + "'"); 165 } 166 167 if (sl) { 168 std::string name = createEnumToStringName(ident, "_enum_to_string_"); 169 std::vector<Expression*> al_args(sl->v().size()); 170 for (unsigned int i = 0; i < sl->v().size(); i++) { 171 std::string str = sl->v()[i]->cast<Id>()->str().str(); 172 if (str.size() >= 2 && str[0] == '\'' && str[str.size() - 1] == '\'') { 173 al_args[i] = 174 new StringLit(Location().introduce(), ASTString(str.substr(1, str.size() - 2))); 175 } else { 176 al_args[i] = new StringLit(Location().introduce(), ASTString(str)); 177 } 178 env.reverseEnum[str] = i + 1; 179 } 180 ArrayLit* al = new ArrayLit(Location().introduce(), al_args); 181 182 if (vd_enumToString) { 183 ret = new AssignI(Location().introduce(), name, al); 184 ret->decl(vd_enumToString); 185 } else { 186 std::vector<TypeInst*> ranges(1); 187 ranges[0] = new TypeInst(Location().introduce(), Type::parint()); 188 TypeInst* ti = new TypeInst(Location().introduce(), Type::parstring(1)); 189 ti->setRanges(ranges); 190 vd_enumToString = new VarDecl(Location().introduce(), ti, name, al); 191 enumItems->addItem(new VarDeclI(Location().introduce(), vd_enumToString)); 192 } 193 194 Type tx = Type::parint(); 195 tx.ot(Type::OT_OPTIONAL); 196 TypeInst* ti_aa = new TypeInst(Location().introduce(), tx); 197 VarDecl* vd_aa = new VarDecl(Location().introduce(), ti_aa, "x"); 198 vd_aa->toplevel(false); 199 TypeInst* ti_ab = new TypeInst(Location().introduce(), Type::parbool()); 200 VarDecl* vd_ab = new VarDecl(Location().introduce(), ti_ab, "b"); 201 vd_ab->toplevel(false); 202 TypeInst* ti_aj = new TypeInst(Location().introduce(), Type::parbool()); 203 VarDecl* vd_aj = new VarDecl(Location().introduce(), ti_aj, "json"); 204 vd_aj->toplevel(false); 205 TypeInst* ti_fi = new TypeInst(Location().introduce(), Type::parstring()); 206 std::vector<VarDecl*> fi_params(3); 207 fi_params[0] = vd_aa; 208 fi_params[1] = vd_ab; 209 fi_params[2] = vd_aj; 210 211 std::vector<Expression*> deopt_args(1); 212 deopt_args[0] = vd_aa->id(); 213 Call* deopt = new Call(Location().introduce(), "deopt", deopt_args); 214 Call* occurs = new Call(Location().introduce(), "occurs", deopt_args); 215 std::vector<Expression*> aa_args(1); 216 aa_args[0] = deopt; 217 ArrayAccess* aa = new ArrayAccess(Location().introduce(), vd_enumToString->id(), aa_args); 218 219 StringLit* sl_absent = new StringLit(Location().introduce(), "<>"); 220 221 ITE* if_absent = 222 new ITE(Location().introduce(), 223 {vd_aj->id(), new StringLit(Location().introduce(), ASTString("null"))}, sl_absent); 224 225 StringLit* json_e_quote = new StringLit(Location().introduce(), ASTString("{\"e\":\"")); 226 StringLit* json_e_quote_end = new StringLit(Location().introduce(), ASTString("\"}")); 227 BinOp* quote_aa = new BinOp(Location().introduce(), json_e_quote, BOT_PLUSPLUS, aa); 228 BinOp* quote_aa2 = new BinOp(Location().introduce(), quote_aa, BOT_PLUSPLUS, json_e_quote_end); 229 230 Call* quote_dzn = new Call(Location().introduce(), ASTString("showDznId"), {aa}); 231 232 std::vector<Expression*> ite_ifelse(2); 233 ite_ifelse[0] = occurs; 234 ite_ifelse[1] = 235 new ITE(Location().introduce(), {vd_ab->id(), quote_dzn, vd_aj->id(), quote_aa2}, aa); 236 237 ITE* ite = new ITE(Location().introduce(), ite_ifelse, if_absent); 238 239 FunctionI* fi = new FunctionI( 240 Location().introduce(), createEnumToStringName(ident, "_toString_"), ti_fi, fi_params, ite); 241 enumItems->addItem(fi); 242 } else { 243 if (vd_enumToString) { 244 /// TODO: find a better solution (don't introduce the vd_enumToString until we 245 /// know it's a non-anonymous enum) 246 vd_enumToString->e(new ArrayLit(Location().introduce(), std::vector<Expression*>())); 247 } 248 { 249 Type tx = Type::parint(); 250 tx.ot(Type::OT_OPTIONAL); 251 TypeInst* ti_aa = new TypeInst(Location().introduce(), tx); 252 VarDecl* vd_aa = new VarDecl(Location().introduce(), ti_aa, "x"); 253 vd_aa->toplevel(false); 254 255 TypeInst* ti_ab = new TypeInst(Location().introduce(), Type::parbool()); 256 VarDecl* vd_ab = new VarDecl(Location().introduce(), ti_ab, "b"); 257 vd_ab->toplevel(false); 258 259 TypeInst* ti_aj = new TypeInst(Location().introduce(), Type::parbool()); 260 VarDecl* vd_aj = new VarDecl(Location().introduce(), ti_aj, "json"); 261 vd_aj->toplevel(false); 262 263 std::vector<Expression*> deopt_args(1); 264 deopt_args[0] = vd_aa->id(); 265 Call* deopt = new Call(Location().introduce(), "deopt", deopt_args); 266 Call* if_absent = new Call(Location().introduce(), "absent", deopt_args); 267 StringLit* sl_absent_dzn = new StringLit(Location().introduce(), "<>"); 268 ITE* sl_absent = new ITE( 269 Location().introduce(), 270 {vd_aj->id(), new StringLit(Location().introduce(), ASTString("null"))}, sl_absent_dzn); 271 272 StringLit* sl_dzn = 273 new StringLit(Location().introduce(), ASTString("to_enum(" + ident->str().str() + ",")); 274 std::vector<Expression*> showIntArgs(1); 275 showIntArgs[0] = deopt; 276 Call* showInt = new Call(Location().introduce(), constants().ids.show, showIntArgs); 277 BinOp* construct_string_dzn = 278 new BinOp(Location().introduce(), sl_dzn, BOT_PLUSPLUS, showInt); 279 StringLit* closing_bracket = new StringLit(Location().introduce(), ASTString(")")); 280 BinOp* construct_string_dzn_2 = 281 new BinOp(Location().introduce(), construct_string_dzn, BOT_PLUSPLUS, closing_bracket); 282 283 StringLit* sl = new StringLit(Location().introduce(), ASTString(ident->str().str() + "_")); 284 BinOp* construct_string = new BinOp(Location().introduce(), sl, BOT_PLUSPLUS, showInt); 285 286 StringLit* json_e_quote = new StringLit(Location().introduce(), ASTString("{\"e\":\"")); 287 StringLit* json_e_quote_end = new StringLit(Location().introduce(), ASTString("\"}")); 288 BinOp* construct_string_json = 289 new BinOp(Location().introduce(), json_e_quote, BOT_PLUSPLUS, construct_string); 290 BinOp* construct_string_json_2 = 291 new BinOp(Location().introduce(), construct_string_json, BOT_PLUSPLUS, json_e_quote_end); 292 293 std::vector<Expression*> if_then(6); 294 if_then[0] = if_absent; 295 if_then[1] = sl_absent; 296 if_then[2] = vd_ab->id(); 297 if_then[3] = construct_string_dzn_2; 298 if_then[4] = vd_aj->id(); 299 if_then[5] = construct_string_json_2; 300 ITE* ite = new ITE(Location().introduce(), if_then, construct_string); 301 302 TypeInst* ti_fi = new TypeInst(Location().introduce(), Type::parstring()); 303 std::vector<VarDecl*> fi_params(3); 304 fi_params[0] = vd_aa; 305 fi_params[1] = vd_ab; 306 fi_params[2] = vd_aj; 307 FunctionI* fi = 308 new FunctionI(Location().introduce(), createEnumToStringName(ident, "_toString_"), ti_fi, 309 fi_params, ite); 310 enumItems->addItem(fi); 311 } 312 } 313 314 { 315 /* 316 317 function _toString_ENUM(array[$U] of opt Foo: x, bool: b, bool: json) = 318 let { 319 array[int] of opt ENUM: xx = array1d(x) 320 } in "[" ++ join(", ", [ _toString_ENUM(xx[i],b,json) | i in index_set(xx) ]) ++ "]"; 321 322 */ 323 324 TIId* tiid = new TIId(Location().introduce(), "U"); 325 TypeInst* ti_range = new TypeInst(Location().introduce(), Type::parint(), tiid); 326 std::vector<TypeInst*> ranges(1); 327 ranges[0] = ti_range; 328 329 Type tx = Type::parint(-1); 330 tx.ot(Type::OT_OPTIONAL); 331 TypeInst* x_ti = new TypeInst(Location().introduce(), tx, ranges, ident); 332 VarDecl* vd_x = new VarDecl(Location().introduce(), x_ti, "x"); 333 vd_x->toplevel(false); 334 335 TypeInst* b_ti = new TypeInst(Location().introduce(), Type::parbool()); 336 VarDecl* vd_b = new VarDecl(Location().introduce(), b_ti, "b"); 337 vd_b->toplevel(false); 338 339 TypeInst* j_ti = new TypeInst(Location().introduce(), Type::parbool()); 340 VarDecl* vd_j = new VarDecl(Location().introduce(), j_ti, "json"); 341 vd_j->toplevel(false); 342 343 TypeInst* xx_range = new TypeInst(Location().introduce(), Type::parint(), NULL); 344 std::vector<TypeInst*> xx_ranges(1); 345 xx_ranges[0] = xx_range; 346 TypeInst* xx_ti = new TypeInst(Location().introduce(), tx, xx_ranges, ident); 347 348 std::vector<Expression*> array1dArgs(1); 349 array1dArgs[0] = vd_x->id(); 350 Call* array1dCall = new Call(Location().introduce(), "array1d", array1dArgs); 351 352 VarDecl* vd_xx = new VarDecl(Location().introduce(), xx_ti, "xx", array1dCall); 353 vd_xx->toplevel(false); 354 355 TypeInst* idx_i_ti = new TypeInst(Location().introduce(), Type::parint()); 356 VarDecl* idx_i = new VarDecl(Location().introduce(), idx_i_ti, "i"); 357 idx_i->toplevel(false); 358 359 std::vector<Expression*> aa_xxi_idx(1); 360 aa_xxi_idx[0] = idx_i->id(); 361 ArrayAccess* aa_xxi = new ArrayAccess(Location().introduce(), vd_xx->id(), aa_xxi_idx); 362 363 std::vector<Expression*> _toString_ENUMArgs(3); 364 _toString_ENUMArgs[0] = aa_xxi; 365 _toString_ENUMArgs[1] = vd_b->id(); 366 _toString_ENUMArgs[2] = vd_j->id(); 367 Call* _toString_ENUM = new Call( 368 Location().introduce(), createEnumToStringName(ident, "_toString_"), _toString_ENUMArgs); 369 370 std::vector<Expression*> index_set_xx_args(1); 371 index_set_xx_args[0] = vd_xx->id(); 372 Call* index_set_xx = new Call(Location().introduce(), "index_set", index_set_xx_args); 373 std::vector<VarDecl*> gen_exps(1); 374 gen_exps[0] = idx_i; 375 Generator gen(gen_exps, index_set_xx, NULL); 376 377 Generators generators; 378 generators._g.push_back(gen); 379 Comprehension* comp = 380 new Comprehension(Location().introduce(), _toString_ENUM, generators, false); 381 382 std::vector<Expression*> join_args(2); 383 join_args[0] = new StringLit(Location().introduce(), ", "); 384 join_args[1] = comp; 385 Call* join = new Call(Location().introduce(), "join", join_args); 386 387 StringLit* sl_open = new StringLit(Location().introduce(), "["); 388 BinOp* bopp0 = new BinOp(Location().introduce(), sl_open, BOT_PLUSPLUS, join); 389 StringLit* sl_close = new StringLit(Location().introduce(), "]"); 390 BinOp* bopp1 = new BinOp(Location().introduce(), bopp0, BOT_PLUSPLUS, sl_close); 391 392 std::vector<Expression*> let_args(1); 393 let_args[0] = vd_xx; 394 Let* let = new Let(Location().introduce(), let_args, bopp1); 395 396 TypeInst* ti_fi = new TypeInst(Location().introduce(), Type::parstring()); 397 std::vector<VarDecl*> fi_params(3); 398 fi_params[0] = vd_x; 399 fi_params[1] = vd_b; 400 fi_params[2] = vd_j; 401 FunctionI* fi = new FunctionI( 402 Location().introduce(), createEnumToStringName(ident, "_toString_"), ti_fi, fi_params, let); 403 enumItems->addItem(fi); 404 } 405 406 { 407 /* 408 409 function _toString_ENUM(opt set of ENUM: x, bool: b, bool: json) = 410 if absent(x) then "<>" else "{" ++ join(", ", [ _toString_ENUM(i,b,json) | i in x ]) ++ "}" 411 endif; 412 413 */ 414 415 Type argType = Type::parsetenum(ident->type().enumId()); 416 argType.ot(Type::OT_OPTIONAL); 417 TypeInst* x_ti = new TypeInst(Location().introduce(), argType, ident); 418 VarDecl* vd_x = new VarDecl(Location().introduce(), x_ti, "x"); 419 vd_x->toplevel(false); 420 421 TypeInst* b_ti = new TypeInst(Location().introduce(), Type::parbool()); 422 VarDecl* vd_b = new VarDecl(Location().introduce(), b_ti, "b"); 423 vd_b->toplevel(false); 424 425 TypeInst* j_ti = new TypeInst(Location().introduce(), Type::parbool()); 426 VarDecl* vd_j = new VarDecl(Location().introduce(), j_ti, "json"); 427 vd_j->toplevel(false); 428 429 TypeInst* idx_i_ti = new TypeInst(Location().introduce(), Type::parint()); 430 VarDecl* idx_i = new VarDecl(Location().introduce(), idx_i_ti, "i"); 431 idx_i->toplevel(false); 432 433 std::vector<Expression*> _toString_ENUMArgs(3); 434 _toString_ENUMArgs[0] = idx_i->id(); 435 _toString_ENUMArgs[1] = vd_b->id(); 436 _toString_ENUMArgs[2] = vd_j->id(); 437 Call* _toString_ENUM = new Call( 438 Location().introduce(), createEnumToStringName(ident, "_toString_"), _toString_ENUMArgs); 439 440 std::vector<Expression*> deopt_args(1); 441 deopt_args[0] = vd_x->id(); 442 Call* deopt = new Call(Location().introduce(), "deopt", deopt_args); 443 Call* if_absent = new Call(Location().introduce(), "absent", deopt_args); 444 StringLit* sl_absent_dzn = new StringLit(Location().introduce(), "<>"); 445 ITE* sl_absent = new ITE(Location().introduce(), 446 {vd_j->id(), new StringLit(Location().introduce(), ASTString("null"))}, 447 sl_absent_dzn); 448 449 std::vector<VarDecl*> gen_exps(1); 450 gen_exps[0] = idx_i; 451 Generator gen(gen_exps, deopt, NULL); 452 453 Generators generators; 454 generators._g.push_back(gen); 455 Comprehension* comp = 456 new Comprehension(Location().introduce(), _toString_ENUM, generators, false); 457 458 std::vector<Expression*> join_args(2); 459 join_args[0] = new StringLit(Location().introduce(), ", "); 460 join_args[1] = comp; 461 Call* join = new Call(Location().introduce(), "join", join_args); 462 463 ITE* json_set = 464 new ITE(Location().introduce(), 465 {vd_j->id(), new StringLit(Location().introduce(), ASTString("\"set\":["))}, 466 new StringLit(Location().introduce(), ASTString(""))); 467 ITE* json_set_close = new ITE( 468 Location().introduce(), {vd_j->id(), new StringLit(Location().introduce(), ASTString("]"))}, 469 new StringLit(Location().introduce(), ASTString(""))); 470 471 StringLit* sl_open = new StringLit(Location().introduce(), "{"); 472 BinOp* bopp0 = new BinOp(Location().introduce(), sl_open, BOT_PLUSPLUS, json_set); 473 BinOp* bopp1 = new BinOp(Location().introduce(), bopp0, BOT_PLUSPLUS, join); 474 BinOp* bopp2 = new BinOp(Location().introduce(), bopp1, BOT_PLUSPLUS, json_set_close); 475 StringLit* sl_close = new StringLit(Location().introduce(), "}"); 476 BinOp* bopp3 = new BinOp(Location().introduce(), bopp2, BOT_PLUSPLUS, sl_close); 477 478 std::vector<Expression*> if_then(2); 479 if_then[0] = if_absent; 480 if_then[1] = sl_absent; 481 ITE* ite = new ITE(Location().introduce(), if_then, bopp3); 482 483 TypeInst* ti_fi = new TypeInst(Location().introduce(), Type::parstring()); 484 std::vector<VarDecl*> fi_params(3); 485 fi_params[0] = vd_x; 486 fi_params[1] = vd_b; 487 fi_params[2] = vd_j; 488 FunctionI* fi = new FunctionI( 489 Location().introduce(), createEnumToStringName(ident, "_toString_"), ti_fi, fi_params, ite); 490 enumItems->addItem(fi); 491 } 492 493 { 494 /* 495 496 function _toString_ENUM(array[$U] of opt set of ENUM: x, bool: b, bool: json) = 497 let { 498 array[int] of opt set of ENUM: xx = array1d(x) 499 } in "[" ++ join(", ", [ _toString_ENUM(xx[i],b,json) | i in index_set(xx) ]) ++ "]"; 500 501 */ 502 503 TIId* tiid = new TIId(Location().introduce(), "U"); 504 TypeInst* ti_range = new TypeInst(Location().introduce(), Type::parint(), tiid); 505 std::vector<TypeInst*> ranges(1); 506 ranges[0] = ti_range; 507 508 Type tx = Type::parsetint(-1); 509 tx.ot(Type::OT_OPTIONAL); 510 TypeInst* x_ti = new TypeInst(Location().introduce(), tx, ranges, ident); 511 VarDecl* vd_x = new VarDecl(Location().introduce(), x_ti, "x"); 512 vd_x->toplevel(false); 513 514 TypeInst* b_ti = new TypeInst(Location().introduce(), Type::parbool()); 515 VarDecl* vd_b = new VarDecl(Location().introduce(), b_ti, "b"); 516 vd_b->toplevel(false); 517 518 TypeInst* j_ti = new TypeInst(Location().introduce(), Type::parbool()); 519 VarDecl* vd_j = new VarDecl(Location().introduce(), j_ti, "json"); 520 vd_j->toplevel(false); 521 522 TypeInst* xx_range = new TypeInst(Location().introduce(), Type::parint(), NULL); 523 std::vector<TypeInst*> xx_ranges(1); 524 xx_ranges[0] = xx_range; 525 TypeInst* xx_ti = new TypeInst(Location().introduce(), tx, xx_ranges, ident); 526 527 std::vector<Expression*> array1dArgs(1); 528 array1dArgs[0] = vd_x->id(); 529 Call* array1dCall = new Call(Location().introduce(), "array1d", array1dArgs); 530 531 VarDecl* vd_xx = new VarDecl(Location().introduce(), xx_ti, "xx", array1dCall); 532 vd_xx->toplevel(false); 533 534 TypeInst* idx_i_ti = new TypeInst(Location().introduce(), Type::parint()); 535 VarDecl* idx_i = new VarDecl(Location().introduce(), idx_i_ti, "i"); 536 idx_i->toplevel(false); 537 538 std::vector<Expression*> aa_xxi_idx(1); 539 aa_xxi_idx[0] = idx_i->id(); 540 ArrayAccess* aa_xxi = new ArrayAccess(Location().introduce(), vd_xx->id(), aa_xxi_idx); 541 542 std::vector<Expression*> _toString_ENUMArgs(3); 543 _toString_ENUMArgs[0] = aa_xxi; 544 _toString_ENUMArgs[1] = vd_b->id(); 545 _toString_ENUMArgs[2] = vd_j->id(); 546 Call* _toString_ENUM = new Call( 547 Location().introduce(), createEnumToStringName(ident, "_toString_"), _toString_ENUMArgs); 548 549 std::vector<Expression*> index_set_xx_args(1); 550 index_set_xx_args[0] = vd_xx->id(); 551 Call* index_set_xx = new Call(Location().introduce(), "index_set", index_set_xx_args); 552 std::vector<VarDecl*> gen_exps(1); 553 gen_exps[0] = idx_i; 554 Generator gen(gen_exps, index_set_xx, NULL); 555 556 Generators generators; 557 generators._g.push_back(gen); 558 Comprehension* comp = 559 new Comprehension(Location().introduce(), _toString_ENUM, generators, false); 560 561 std::vector<Expression*> join_args(2); 562 join_args[0] = new StringLit(Location().introduce(), ", "); 563 join_args[1] = comp; 564 Call* join = new Call(Location().introduce(), "join", join_args); 565 566 StringLit* sl_open = new StringLit(Location().introduce(), "["); 567 BinOp* bopp0 = new BinOp(Location().introduce(), sl_open, BOT_PLUSPLUS, join); 568 StringLit* sl_close = new StringLit(Location().introduce(), "]"); 569 BinOp* bopp1 = new BinOp(Location().introduce(), bopp0, BOT_PLUSPLUS, sl_close); 570 571 std::vector<Expression*> let_args(1); 572 let_args[0] = vd_xx; 573 Let* let = new Let(Location().introduce(), let_args, bopp1); 574 575 TypeInst* ti_fi = new TypeInst(Location().introduce(), Type::parstring()); 576 std::vector<VarDecl*> fi_params(3); 577 fi_params[0] = vd_x; 578 fi_params[1] = vd_b; 579 fi_params[2] = vd_j; 580 FunctionI* fi = new FunctionI( 581 Location().introduce(), createEnumToStringName(ident, "_toString_"), ti_fi, fi_params, let); 582 enumItems->addItem(fi); 583 } 584 return ret; 585} 586 587void TopoSorter::add(EnvI& env, VarDeclI* vdi, bool handleEnums, Model* enumItems) { 588 VarDecl* vd = vdi->e(); 589 if (handleEnums && vd->ti()->isEnum()) { 590 unsigned int enumId = env.registerEnum(vdi); 591 Type vdt = vd->type(); 592 vdt.enumId(enumId); 593 vd->ti()->type(vdt); 594 vd->type(vdt); 595 596 if (vd->e()) { 597 (void)createEnumMapper(env, model, enumId, vd, NULL, enumItems); 598 } else { 599 GCLock lock; 600 std::string name = createEnumToStringName(vd->id(), "_enum_to_string_"); 601 std::vector<TypeInst*> ranges(1); 602 ranges[0] = new TypeInst(Location().introduce(), Type::parint()); 603 TypeInst* ti = new TypeInst(Location().introduce(), Type::parstring(1)); 604 ti->setRanges(ranges); 605 VarDecl* vd_enumToString = new VarDecl(Location().introduce(), ti, name, NULL); 606 enumItems->addItem(new VarDeclI(Location().introduce(), vd_enumToString)); 607 } 608 } 609 scopes.add(env, vd); 610} 611 612VarDecl* TopoSorter::get(EnvI& env, const ASTString& id_v, const Location& loc) { 613 GCLock lock; 614 Id* id = new Id(Location(), id_v, NULL); 615 VarDecl* decl = scopes.find(id); 616 if (decl == NULL) { 617 throw TypeError(env, loc, "undefined identifier `" + id->str().str() + "'"); 618 } 619 return decl; 620} 621 622VarDecl* TopoSorter::checkId(EnvI& env, Id* ident, const Location& loc) { 623 VarDecl* decl = scopes.find(ident); 624 if (decl == NULL) { 625 GCLock lock; 626 throw TypeError(env, loc, "undefined identifier `" + ident->str().str() + "'"); 627 } 628 PosMap::iterator pi = pos.find(decl); 629 if (pi == pos.end()) { 630 // new id 631 scopes.push(true); 632 run(env, decl); 633 scopes.pop(); 634 } else { 635 // previously seen, check if circular 636 if (pi->second == -1) { 637 GCLock lock; 638 throw TypeError(env, loc, "circular definition of `" + ident->str().str() + "'"); 639 } 640 } 641 return decl; 642} 643 644VarDecl* TopoSorter::checkId(EnvI& env, const ASTString& id_v, const Location& loc) { 645 GCLock lock; 646 Id* id = new Id(loc, id_v, NULL); 647 return checkId(env, id, loc); 648} 649 650void TopoSorter::run(EnvI& env, Expression* e) { 651 if (e == NULL) return; 652 switch (e->eid()) { 653 case Expression::E_INTLIT: 654 case Expression::E_FLOATLIT: 655 case Expression::E_BOOLLIT: 656 case Expression::E_STRINGLIT: 657 case Expression::E_ANON: 658 break; 659 case Expression::E_SETLIT: { 660 SetLit* sl = e->cast<SetLit>(); 661 if (sl->isv() == NULL && sl->fsv() == NULL) 662 for (unsigned int i = 0; i < sl->v().size(); i++) run(env, sl->v()[i]); 663 } break; 664 case Expression::E_ID: { 665 if (e != constants().absent) { 666 VarDecl* vd = checkId(env, e->cast<Id>(), e->loc()); 667 e->cast<Id>()->decl(vd); 668 } 669 } break; 670 case Expression::E_ARRAYLIT: { 671 ArrayLit* al = e->cast<ArrayLit>(); 672 for (unsigned int i = 0; i < al->size(); i++) run(env, (*al)[i]); 673 } break; 674 case Expression::E_ARRAYACCESS: { 675 ArrayAccess* ae = e->cast<ArrayAccess>(); 676 run(env, ae->v()); 677 for (unsigned int i = 0; i < ae->idx().size(); i++) run(env, ae->idx()[i]); 678 } break; 679 case Expression::E_COMP: { 680 Comprehension* ce = e->cast<Comprehension>(); 681 scopes.push(false); 682 for (int i = 0; i < ce->n_generators(); i++) { 683 run(env, ce->in(i)); 684 for (int j = 0; j < ce->n_decls(i); j++) { 685 run(env, ce->decl(i, j)); 686 scopes.add(env, ce->decl(i, j)); 687 } 688 if (ce->where(i)) run(env, ce->where(i)); 689 } 690 run(env, ce->e()); 691 scopes.pop(); 692 } break; 693 case Expression::E_ITE: { 694 ITE* ite = e->cast<ITE>(); 695 for (int i = 0; i < ite->size(); i++) { 696 run(env, ite->e_if(i)); 697 run(env, ite->e_then(i)); 698 } 699 run(env, ite->e_else()); 700 } break; 701 case Expression::E_BINOP: { 702 BinOp* be = e->cast<BinOp>(); 703 std::vector<Expression*> todo; 704 todo.push_back(be->lhs()); 705 todo.push_back(be->rhs()); 706 while (!todo.empty()) { 707 Expression* e = todo.back(); 708 todo.pop_back(); 709 if (BinOp* e_bo = e->dyn_cast<BinOp>()) { 710 todo.push_back(e_bo->lhs()); 711 todo.push_back(e_bo->rhs()); 712 for (ExpressionSetIter it = e_bo->ann().begin(); it != e_bo->ann().end(); ++it) 713 run(env, *it); 714 } else { 715 run(env, e); 716 } 717 } 718 } break; 719 case Expression::E_UNOP: { 720 UnOp* ue = e->cast<UnOp>(); 721 run(env, ue->e()); 722 } break; 723 case Expression::E_CALL: { 724 Call* ce = e->cast<Call>(); 725 for (unsigned int i = 0; i < ce->n_args(); i++) run(env, ce->arg(i)); 726 } break; 727 case Expression::E_VARDECL: { 728 VarDecl* ve = e->cast<VarDecl>(); 729 PosMap::iterator pi = pos.find(ve); 730 if (pi == pos.end()) { 731 pos.insert(std::pair<VarDecl*, int>(ve, -1)); 732 run(env, ve->ti()); 733 run(env, ve->e()); 734 ve->payload(static_cast<int>(decls.size())); 735 decls.push_back(ve); 736 pi = pos.find(ve); 737 pi->second = static_cast<int>(decls.size()) - 1; 738 } else { 739 assert(pi->second != -1); 740 } 741 } break; 742 case Expression::E_TI: { 743 TypeInst* ti = e->cast<TypeInst>(); 744 for (unsigned int i = 0; i < ti->ranges().size(); i++) run(env, ti->ranges()[i]); 745 run(env, ti->domain()); 746 } break; 747 case Expression::E_TIID: 748 break; 749 case Expression::E_LET: { 750 Let* let = e->cast<Let>(); 751 scopes.push(false); 752 for (unsigned int i = 0; i < let->let().size(); i++) { 753 run(env, let->let()[i]); 754 if (VarDecl* vd = let->let()[i]->dyn_cast<VarDecl>()) { 755 scopes.add(env, vd); 756 } 757 } 758 run(env, let->in()); 759 VarDeclCmp poscmp(pos); 760 std::stable_sort(let->let().begin(), let->let().end(), poscmp); 761 for (unsigned int i = 0; i < let->let().size(); i++) { 762 if (VarDecl* vd = let->let()[i]->dyn_cast<VarDecl>()) { 763 let->let_orig()[i] = vd->e(); 764 } else { 765 let->let_orig()[i] = NULL; 766 } 767 } 768 scopes.pop(); 769 } break; 770 } 771 if (env.ignoreUnknownIds) { 772 std::vector<Expression*> toDelete; 773 for (ExpressionSetIter it = e->ann().begin(); it != e->ann().end(); ++it) { 774 try { 775 run(env, *it); 776 } catch (TypeError&) { 777 toDelete.push_back(*it); 778 } 779 for (Expression* de : toDelete) e->ann().remove(de); 780 } 781 } else { 782 for (ExpressionSetIter it = e->ann().begin(); it != e->ann().end(); ++it) { 783 run(env, *it); 784 } 785 } 786} 787 788KeepAlive addCoercion(EnvI& env, Model* m, Expression* e, const Type& funarg_t) { 789 if (e->isa<ArrayAccess>() && e->type().dim() > 0) { 790 ArrayAccess* aa = e->cast<ArrayAccess>(); 791 // Turn ArrayAccess into a slicing operation 792 std::vector<Expression*> slice; 793 slice.reserve(aa->idx().size()); 794 std::vector<Expression*> ndims; 795 GCLock lock; 796 for (unsigned int i = 0; i < aa->idx().size(); i++) { 797 if (aa->idx()[i]->type().is_set()) { 798 bool needIdxSet = true; 799 bool needInter = true; 800 if (SetLit* sl = aa->idx()[i]->dyn_cast<SetLit>()) { 801 if (sl->isv() && sl->isv()->size() == 1) { 802 if (sl->isv()->min().isFinite() && sl->isv()->max().isFinite()) { 803 ndims.push_back(sl); 804 needIdxSet = false; 805 } else if (sl->isv()->min() == -IntVal::infinity() && 806 sl->isv()->max() == IntVal::infinity()) { 807 needInter = false; 808 } 809 } 810 } 811 if (needIdxSet) { 812 std::ostringstream oss; 813 oss << "index_set"; 814 if (aa->idx().size() > 1) { 815 oss << "_" << (i + 1) << "of" << aa->idx().size(); 816 } 817 std::vector<Expression*> origIdxsetArgs(1); 818 origIdxsetArgs[0] = aa->v(); 819 Call* origIdxset = new Call(aa->v()->loc(), ASTString(oss.str()), origIdxsetArgs); 820 FunctionI* fi = m->matchFn(env, origIdxset, false); 821 if (!fi) throw TypeError(env, e->loc(), "missing builtin " + oss.str()); 822 origIdxset->type(fi->rtype(env, origIdxsetArgs, false)); 823 origIdxset->decl(fi); 824 if (needInter) { 825 BinOp* inter = new BinOp(aa->idx()[i]->loc(), aa->idx()[i], BOT_INTERSECT, origIdxset); 826 inter->type(Type::parsetint()); 827 ndims.push_back(inter); 828 } else { 829 ndims.push_back(origIdxset); 830 } 831 } 832 slice.push_back(aa->idx()[i]); 833 } else { 834 BinOp* bo = new BinOp(aa->idx()[i]->loc(), aa->idx()[i], BOT_DOTDOT, aa->idx()[i]); 835 bo->type(Type::parsetint()); 836 slice.push_back(bo); 837 } 838 } 839 ArrayLit* a_slice = new ArrayLit(e->loc().introduce(), slice); 840 a_slice->type(Type::parsetint(1)); 841 ArrayLit* a_ndims = new ArrayLit(e->loc().introduce(), ndims); 842 a_ndims->type(Type::parsetint(1)); 843 std::vector<Expression*> args = {aa->v(), a_slice, a_ndims}; 844 Call* c = new Call(e->loc(), ASTString("slice_Xd"), args); 845 FunctionI* fi = m->matchFn(env, c, false); 846 if (!fi) throw TypeError(env, e->loc(), "missing builtin slice_Xd"); 847 c->type(fi->rtype(env, args, false)); 848 c->decl(fi); 849 e = c; 850 } 851 if (e->type().dim() == funarg_t.dim() && 852 (funarg_t.bt() == Type::BT_BOT || funarg_t.bt() == Type::BT_TOP || 853 e->type().bt() == funarg_t.bt() || e->type().bt() == Type::BT_BOT)) 854 return e; 855 std::vector<Expression*> args(1); 856 args[0] = e; 857 GCLock lock; 858 Call* c = NULL; 859 if (e->type().dim() == 0 && funarg_t.dim() != 0) { 860 if (e->type().isvar()) { 861 throw TypeError(env, e->loc(), "cannot coerce var set into array"); 862 } 863 if (e->type().isopt()) { 864 throw TypeError(env, e->loc(), "cannot coerce opt set into array"); 865 } 866 std::vector<Expression*> set2a_args(1); 867 set2a_args[0] = e; 868 Call* set2a = new Call(e->loc(), ASTString("set2array"), set2a_args); 869 FunctionI* fi = m->matchFn(env, set2a, false); 870 if (fi) { 871 set2a->type(fi->rtype(env, args, false)); 872 set2a->decl(fi); 873 e = set2a; 874 } 875 } 876 if (funarg_t.bt() == Type::BT_TOP || e->type().bt() == funarg_t.bt() || 877 e->type().bt() == Type::BT_BOT) { 878 KeepAlive ka(e); 879 return ka; 880 } 881 if (e->type().bt() == Type::BT_BOOL) { 882 if (funarg_t.bt() == Type::BT_INT) { 883 c = new Call(e->loc(), constants().ids.bool2int, args); 884 } else if (funarg_t.bt() == Type::BT_FLOAT) { 885 c = new Call(e->loc(), constants().ids.bool2float, args); 886 } 887 } else if (e->type().bt() == Type::BT_INT) { 888 if (funarg_t.bt() == Type::BT_FLOAT) { 889 c = new Call(e->loc(), constants().ids.int2float, args); 890 } 891 } 892 if (c) { 893 FunctionI* fi = m->matchFn(env, c, false); 894 assert(fi); 895 c->type(fi->rtype(env, args, false)); 896 c->decl(fi); 897 KeepAlive ka(c); 898 return ka; 899 } 900 throw TypeError(env, e->loc(), 901 "cannot determine coercion from type " + e->type().toString(env) + " to type " + 902 funarg_t.toString(env)); 903} 904KeepAlive addCoercion(EnvI& env, Model* m, Expression* e, Expression* funarg) { 905 return addCoercion(env, m, e, funarg->type()); 906} 907 908template <bool ignoreVarDecl> 909class Typer { 910public: 911 EnvI& _env; 912 Model* _model; 913 std::vector<TypeError>& _typeErrors; 914 bool _ignoreUndefined; 915 Typer(EnvI& env, Model* model, std::vector<TypeError>& typeErrors, bool ignoreUndefined) 916 : _env(env), _model(model), _typeErrors(typeErrors), _ignoreUndefined(ignoreUndefined) {} 917 /// Check annotations when expression is finished 918 void exit(Expression* e) { 919 for (ExpressionSetIter it = e->ann().begin(); it != e->ann().end(); ++it) 920 if (!(*it)->type().isann()) 921 throw TypeError(_env, (*it)->loc(), 922 "expected annotation, got `" + (*it)->type().toString(_env) + "'"); 923 } 924 bool enter(Expression*) { return true; } 925 /// Visit integer literal 926 void vIntLit(const IntLit&) {} 927 /// Visit floating point literal 928 void vFloatLit(const FloatLit&) {} 929 /// Visit Boolean literal 930 void vBoolLit(const BoolLit&) {} 931 /// Visit set literal 932 void vSetLit(SetLit& sl) { 933 Type ty; 934 ty.st(Type::ST_SET); 935 if (sl.isv()) { 936 ty.bt(Type::BT_INT); 937 ty.enumId(sl.type().enumId()); 938 sl.type(ty); 939 return; 940 } 941 unsigned int enumId = sl.v().size() > 0 ? sl.v()[0]->type().enumId() : 0; 942 for (unsigned int i = 0; i < sl.v().size(); i++) { 943 if (sl.v()[i]->type().dim() > 0) 944 throw TypeError(_env, sl.v()[i]->loc(), "set literals cannot contain arrays"); 945 if (sl.v()[i]->type().isvar()) ty.ti(Type::TI_VAR); 946 if (sl.v()[i]->type().isopt()) 947 throw TypeError(_env, sl.v()[i]->loc(), "set literals cannot contain option type values"); 948 if (sl.v()[i]->type().cv()) ty.cv(true); 949 if (enumId != sl.v()[i]->type().enumId()) enumId = 0; 950 if (!Type::bt_subtype(sl.v()[i]->type(), ty, true)) { 951 if (ty.bt() == Type::BT_UNKNOWN || Type::bt_subtype(ty, sl.v()[i]->type(), true)) { 952 ty.bt(sl.v()[i]->type().bt()); 953 } else { 954 throw TypeError(_env, sl.loc(), "non-uniform set literal"); 955 } 956 } 957 } 958 ty.enumId(enumId); 959 if (ty.bt() == Type::BT_UNKNOWN) { 960 ty.bt(Type::BT_BOT); 961 } else { 962 if (ty.isvar() && ty.bt() != Type::BT_INT) { 963 if (ty.bt() == Type::BT_BOOL) 964 ty.bt(Type::BT_INT); 965 else 966 throw TypeError(_env, sl.loc(), "cannot coerce set literal element to var int"); 967 } 968 for (unsigned int i = 0; i < sl.v().size(); i++) { 969 sl.v()[i] = addCoercion(_env, _model, sl.v()[i], ty)(); 970 } 971 } 972 sl.type(ty); 973 } 974 /// Visit string literal 975 void vStringLit(const StringLit&) {} 976 /// Visit identifier 977 void vId(Id& id) { 978 if (&id != constants().absent) { 979 assert(!id.decl()->type().isunknown()); 980 id.type(id.decl()->type()); 981 } 982 } 983 /// Visit anonymous variable 984 void vAnonVar(const AnonVar&) {} 985 /// Visit array literal 986 void vArrayLit(ArrayLit& al) { 987 Type ty; 988 ty.dim(al.dims()); 989 std::vector<AnonVar*> anons; 990 bool haveAbsents = false; 991 bool haveInferredType = false; 992 for (unsigned int i = 0; i < al.size(); i++) { 993 Expression* vi = al[i]; 994 if (vi->type().dim() > 0) 995 throw TypeError(_env, vi->loc(), "arrays cannot be elements of arrays"); 996 if (vi == constants().absent) haveAbsents = true; 997 AnonVar* av = vi->dyn_cast<AnonVar>(); 998 if (av) { 999 ty.ti(Type::TI_VAR); 1000 anons.push_back(av); 1001 } else if (vi->type().isvar()) { 1002 ty.ti(Type::TI_VAR); 1003 } 1004 if (vi->type().cv()) ty.cv(true); 1005 if (vi->type().isopt()) { 1006 ty.ot(Type::OT_OPTIONAL); 1007 } 1008 1009 if (ty.bt() == Type::BT_UNKNOWN) { 1010 if (av == NULL) { 1011 if (haveInferredType) { 1012 if (ty.st() != vi->type().st() && vi->type().ot() != Type::OT_OPTIONAL) { 1013 throw TypeError(_env, al.loc(), "non-uniform array literal"); 1014 } 1015 } else { 1016 haveInferredType = true; 1017 ty.st(vi->type().st()); 1018 } 1019 if (vi->type().bt() != Type::BT_BOT) { 1020 ty.bt(vi->type().bt()); 1021 ty.enumId(vi->type().enumId()); 1022 } 1023 } 1024 } else { 1025 if (av == NULL) { 1026 if (vi->type().bt() == Type::BT_BOT) { 1027 if (vi->type().st() != ty.st() && vi->type().ot() != Type::OT_OPTIONAL) { 1028 throw TypeError(_env, al.loc(), "non-uniform array literal"); 1029 } 1030 if (vi->type().enumId() != 0 && ty.enumId() != vi->type().enumId()) { 1031 ty.enumId(0); 1032 } 1033 } else { 1034 unsigned int tyEnumId = ty.enumId(); 1035 ty.enumId(vi->type().enumId()); 1036 if (Type::bt_subtype(ty, vi->type(), true)) { 1037 ty.bt(vi->type().bt()); 1038 } 1039 if (tyEnumId != vi->type().enumId()) ty.enumId(0); 1040 if (!Type::bt_subtype(vi->type(), ty, true) || ty.st() != vi->type().st()) { 1041 throw TypeError(_env, al.loc(), "non-uniform array literal"); 1042 } 1043 } 1044 } 1045 } 1046 } 1047 if (ty.bt() == Type::BT_UNKNOWN) { 1048 ty.bt(Type::BT_BOT); 1049 if (!anons.empty()) 1050 throw TypeError(_env, al.loc(), 1051 "array literal must contain at least one non-anonymous variable"); 1052 if (haveAbsents) 1053 throw TypeError(_env, al.loc(), "array literal must contain at least one non-absent value"); 1054 } else { 1055 Type at = ty; 1056 at.dim(0); 1057 if (at.ti() == Type::TI_VAR && at.st() == Type::ST_SET && at.bt() != Type::BT_INT) { 1058 if (at.bt() == Type::BT_BOOL) { 1059 ty.bt(Type::BT_INT); 1060 at.bt(Type::BT_INT); 1061 } else { 1062 throw TypeError(_env, al.loc(), "cannot coerce array element to var set of int"); 1063 } 1064 } 1065 for (unsigned int i = 0; i < anons.size(); i++) { 1066 anons[i]->type(at); 1067 } 1068 for (unsigned int i = 0; i < al.size(); i++) { 1069 al.set(i, addCoercion(_env, _model, al[i], at)()); 1070 } 1071 } 1072 if (ty.enumId() != 0) { 1073 std::vector<unsigned int> enumIds(ty.dim() + 1); 1074 for (int i = 0; i < ty.dim(); i++) enumIds[i] = 0; 1075 enumIds[ty.dim()] = ty.enumId(); 1076 ty.enumId(_env.registerArrayEnum(enumIds)); 1077 } 1078 al.type(ty); 1079 } 1080 /// Visit array access 1081 void vArrayAccess(ArrayAccess& aa) { 1082 if (aa.v()->type().dim() == 0) { 1083 if (aa.v()->type().st() == Type::ST_SET) { 1084 Type tv = aa.v()->type(); 1085 tv.st(Type::ST_PLAIN); 1086 tv.dim(1); 1087 aa.v(addCoercion(_env, _model, aa.v(), tv)()); 1088 } else { 1089 std::ostringstream oss; 1090 oss << "array access attempted on expression of type `" << aa.v()->type().toString(_env) 1091 << "'"; 1092 throw TypeError(_env, aa.v()->loc(), oss.str()); 1093 } 1094 } else if (aa.v()->isa<ArrayAccess>()) { 1095 aa.v(addCoercion(_env, _model, aa.v(), aa.v()->type())()); 1096 } 1097 if (aa.v()->type().dim() != aa.idx().size()) { 1098 std::ostringstream oss; 1099 oss << aa.v()->type().dim() << "-dimensional array accessed with " << aa.idx().size() 1100 << (aa.idx().size() == 1 ? " expression" : " expressions"); 1101 throw TypeError(_env, aa.v()->loc(), oss.str()); 1102 } 1103 Type tt = aa.v()->type(); 1104 if (tt.enumId() != 0) { 1105 const std::vector<unsigned int>& arrayEnumIds = _env.getArrayEnum(tt.enumId()); 1106 1107 for (unsigned int i = 0; i < arrayEnumIds.size() - 1; i++) { 1108 Expression* aai = aa.idx()[i]; 1109 // Check if index is slice operator, and convert to correct enum type 1110 if (SetLit* aai_sl = aai->dyn_cast<SetLit>()) { 1111 if (IntSetVal* aai_isv = aai_sl->isv()) { 1112 if (aai_isv->min() == -IntVal::infinity() && aai_isv->max() == IntVal::infinity()) { 1113 Type aai_sl_t = aai_sl->type(); 1114 aai_sl_t.enumId(arrayEnumIds[i]); 1115 aai_sl->type(aai_sl_t); 1116 } 1117 } 1118 } else if (BinOp* aai_bo = aai->dyn_cast<BinOp>()) { 1119 if (aai_bo->op() == BOT_DOTDOT) { 1120 Type aai_bo_t = aai_bo->type(); 1121 if (IntLit* il = aai_bo->lhs()->dyn_cast<IntLit>()) { 1122 if (il->v() == -IntVal::infinity()) { 1123 // Expression is ..X, so result gets enum type of X 1124 aai_bo_t.enumId(aai_bo->rhs()->type().enumId()); 1125 } 1126 } else if (IntLit* il = aai_bo->rhs()->dyn_cast<IntLit>()) { 1127 if (il->v() == IntVal::infinity()) { 1128 // Expression is X.., so result gets enum type of X 1129 aai_bo_t.enumId(aai_bo->lhs()->type().enumId()); 1130 } 1131 } 1132 aai_bo->type(aai_bo_t); 1133 } 1134 } 1135 1136 if (arrayEnumIds[i] != 0) { 1137 if (aa.idx()[i]->type().enumId() != arrayEnumIds[i]) { 1138 std::ostringstream oss; 1139 oss << "array index "; 1140 if (aa.idx().size() > 1) { 1141 oss << (i + 1) << " "; 1142 } 1143 oss << "must be `" << _env.getEnum(arrayEnumIds[i])->e()->id()->str().str() 1144 << "', but is `" << aa.idx()[i]->type().toString(_env) << "'"; 1145 throw TypeError(_env, aa.loc(), oss.str()); 1146 } 1147 } 1148 } 1149 tt.enumId(arrayEnumIds[arrayEnumIds.size() - 1]); 1150 } 1151 int n_dimensions = 0; 1152 bool isVarAccess = false; 1153 bool isSlice = false; 1154 for (unsigned int i = 0; i < aa.idx().size(); i++) { 1155 Expression* aai = aa.idx()[i]; 1156 if (aai->isa<AnonVar>()) { 1157 aai->type(Type::varint()); 1158 } 1159 if ((aai->type().bt() != Type::BT_INT && aai->type().bt() != Type::BT_BOOL) || 1160 aai->type().dim() != 0) { 1161 throw TypeError(_env, aa.loc(), 1162 "array index must be `int' or `set of int', but is `" + 1163 aai->type().toString(_env) + "'"); 1164 } 1165 if (aai->type().is_set()) { 1166 if (isVarAccess || aai->type().isvar()) { 1167 throw TypeError(_env, aa.loc(), 1168 "array slicing with variable range or index not supported"); 1169 } 1170 isSlice = true; 1171 aa.idx()[i] = addCoercion(_env, _model, aai, Type::varsetint())(); 1172 n_dimensions++; 1173 } else { 1174 aa.idx()[i] = addCoercion(_env, _model, aai, Type::varint())(); 1175 } 1176 1177 if (aai->type().isopt()) { 1178 tt.ot(Type::OT_OPTIONAL); 1179 } 1180 if (aai->type().isvar()) { 1181 isVarAccess = true; 1182 if (isSlice) { 1183 throw TypeError(_env, aa.loc(), 1184 "array slicing with variable range or index not supported"); 1185 } 1186 tt.ti(Type::TI_VAR); 1187 if (tt.bt() == Type::BT_ANN || tt.bt() == Type::BT_STRING) { 1188 throw TypeError(_env, aai->loc(), 1189 std::string("array access using a variable not supported for array of ") + 1190 (tt.bt() == Type::BT_ANN ? "ann" : "string")); 1191 } 1192 } 1193 tt.dim(n_dimensions); 1194 if (aai->type().cv()) tt.cv(true); 1195 } 1196 aa.type(tt); 1197 } 1198 /// Visit array comprehension 1199 void vComprehension(Comprehension& c) { 1200 Type tt = c.e()->type(); 1201 typedef std::unordered_map<VarDecl*, std::pair<int, int> > genMap_t; 1202 typedef std::unordered_map<VarDecl*, std::vector<Expression*> > whereMap_t; 1203 genMap_t generatorMap; 1204 whereMap_t whereMap; 1205 int declCount = 0; 1206 bool didMoveWheres = false; 1207 for (int i = 0; i < c.n_generators(); i++) { 1208 for (int j = 0; j < c.n_decls(i); j++) { 1209 generatorMap[c.decl(i, j)] = std::pair<int, int>(i, declCount++); 1210 whereMap[c.decl(i, j)] = std::vector<Expression*>(); 1211 } 1212 Expression* g_in = c.in(i); 1213 if (g_in) { 1214 const Type& ty_in = g_in->type(); 1215 if (ty_in == Type::varsetint()) { 1216 tt.ot(Type::OT_OPTIONAL); 1217 tt.ti(Type::TI_VAR); 1218 tt.cv(true); 1219 } 1220 if (ty_in.cv()) tt.cv(true); 1221 if (c.where(i)) { 1222 if (c.where(i)->type() == Type::varbool()) { 1223 tt.ot(Type::OT_OPTIONAL); 1224 tt.ti(Type::TI_VAR); 1225 tt.cv(true); 1226 } else if (c.where(i)->type() != Type::parbool()) { 1227 throw TypeError( 1228 _env, c.where(i)->loc(), 1229 "where clause must be bool, but is `" + c.where(i)->type().toString(_env) + "'"); 1230 } 1231 if (c.where(i)->type().cv()) tt.cv(true); 1232 1233 // Try to move parts of the where clause to earlier generators 1234 std::vector<Expression*> wherePartsStack; 1235 std::vector<Expression*> whereParts; 1236 wherePartsStack.push_back(c.where(i)); 1237 while (!wherePartsStack.empty()) { 1238 Expression* e = wherePartsStack.back(); 1239 wherePartsStack.pop_back(); 1240 if (BinOp* bo = e->dyn_cast<BinOp>()) { 1241 if (bo->op() == BOT_AND) { 1242 wherePartsStack.push_back(bo->rhs()); 1243 wherePartsStack.push_back(bo->lhs()); 1244 } else { 1245 whereParts.push_back(e); 1246 } 1247 } else { 1248 whereParts.push_back(e); 1249 } 1250 } 1251 1252 for (unsigned int wpi = 0; wpi < whereParts.size(); wpi++) { 1253 Expression* wp = whereParts[wpi]; 1254 class FindLatestGen : public EVisitor { 1255 public: 1256 int decl_idx; 1257 VarDecl* decl; 1258 const genMap_t& generatorMap; 1259 Comprehension* comp; 1260 FindLatestGen(const genMap_t& generatorMap0, Comprehension* comp0) 1261 : decl_idx(-1), 1262 decl(comp0->decl(0, 0)), 1263 generatorMap(generatorMap0), 1264 comp(comp0) {} 1265 void vId(const Id& ident) { 1266 genMap_t::const_iterator it = generatorMap.find(ident.decl()); 1267 if (it != generatorMap.end() && it->second.second > decl_idx) { 1268 decl_idx = it->second.second; 1269 decl = ident.decl(); 1270 int gen = it->second.first; 1271 while (comp->in(gen) == NULL && gen < comp->n_generators() - 1) { 1272 decl_idx++; 1273 gen++; 1274 decl = comp->decl(gen, 0); 1275 } 1276 } 1277 } 1278 } flg(generatorMap, &c); 1279 topDown(flg, wp); 1280 whereMap[flg.decl].push_back(wp); 1281 1282 if (flg.decl_idx < declCount - 1) didMoveWheres = true; 1283 } 1284 } 1285 } else { 1286 assert(c.where(i) != NULL); 1287 whereMap[c.decl(i, 0)].push_back(c.where(i)); 1288 } 1289 } 1290 1291 if (didMoveWheres) { 1292 Generators generators; 1293 for (int i = 0; i < c.n_generators(); i++) { 1294 std::vector<VarDecl*> decls; 1295 for (int j = 0; j < c.n_decls(i); j++) { 1296 decls.push_back(c.decl(i, j)); 1297 if (whereMap[c.decl(i, j)].size() != 0) { 1298 // need a generator for all the decls up to this point 1299 Expression* whereExpr = whereMap[c.decl(i, j)][0]; 1300 for (unsigned int k = 1; k < whereMap[c.decl(i, j)].size(); k++) { 1301 GCLock lock; 1302 BinOp* bo = 1303 new BinOp(Location().introduce(), whereExpr, BOT_AND, whereMap[c.decl(i, j)][k]); 1304 Type bo_t = whereMap[c.decl(i, j)][k]->type().ispar() && whereExpr->type().ispar() 1305 ? Type::parbool() 1306 : Type::varbool(); 1307 bo->type(bo_t); 1308 whereExpr = bo; 1309 } 1310 generators._g.push_back(Generator(decls, c.in(i), whereExpr)); 1311 decls.clear(); 1312 } else if (j == c.n_decls(i) - 1) { 1313 generators._g.push_back(Generator(decls, c.in(i), NULL)); 1314 decls.clear(); 1315 } 1316 } 1317 } 1318 GCLock lock; 1319 c.init(c.e(), generators); 1320 } 1321 1322 if (c.set()) { 1323 if (c.e()->type().dim() != 0 || c.e()->type().st() == Type::ST_SET) 1324 throw TypeError(_env, c.e()->loc(), 1325 "set comprehension expression must be scalar, but is `" + 1326 c.e()->type().toString(_env) + "'"); 1327 tt.st(Type::ST_SET); 1328 if (tt.isvar()) { 1329 c.e(addCoercion(_env, _model, c.e(), Type::varint())()); 1330 tt.bt(Type::BT_INT); 1331 } 1332 } else { 1333 if (c.e()->type().dim() != 0) 1334 throw TypeError(_env, c.e()->loc(), "array comprehension expression cannot be an array"); 1335 tt.dim(1); 1336 if (tt.enumId() != 0) { 1337 std::vector<unsigned int> enumIds(2); 1338 enumIds[0] = 0; 1339 enumIds[1] = tt.enumId(); 1340 tt.enumId(_env.registerArrayEnum(enumIds)); 1341 } 1342 } 1343 c.type(tt); 1344 } 1345 /// Visit array comprehension generator 1346 void vComprehensionGenerator(Comprehension& c, int gen_i) { 1347 Expression* g_in = c.in(gen_i); 1348 if (g_in == NULL) { 1349 // This is an "assignment generator" (i = expr) 1350 assert(c.where(gen_i) != NULL); 1351 assert(c.n_decls(gen_i) == 1); 1352 const Type& ty_where = c.where(gen_i)->type(); 1353 c.decl(gen_i, 0)->type(ty_where); 1354 c.decl(gen_i, 0)->ti()->type(ty_where); 1355 } else { 1356 const Type& ty_in = g_in->type(); 1357 if (ty_in != Type::varsetint() && ty_in != Type::parsetint() && ty_in.dim() != 1) { 1358 throw TypeError(_env, g_in->loc(), 1359 "generator expression must be (par or var) set of int or one-dimensional " 1360 "array, but is `" + 1361 ty_in.toString(_env) + "'"); 1362 } 1363 Type ty_id; 1364 bool needIntLit = false; 1365 if (ty_in.dim() == 0) { 1366 ty_id = Type::parint(); 1367 ty_id.enumId(ty_in.enumId()); 1368 needIntLit = true; 1369 } else { 1370 ty_id = ty_in; 1371 if (ty_in.enumId() != 0) { 1372 const std::vector<unsigned int>& enumIds = _env.getArrayEnum(ty_in.enumId()); 1373 ty_id.enumId(enumIds.back()); 1374 } 1375 ty_id.dim(0); 1376 } 1377 for (int j = 0; j < c.n_decls(gen_i); j++) { 1378 if (needIntLit) { 1379 GCLock lock; 1380 c.decl(gen_i, j)->e(IntLit::aEnum(0, ty_id.enumId())); 1381 } 1382 c.decl(gen_i, j)->type(ty_id); 1383 c.decl(gen_i, j)->ti()->type(ty_id); 1384 } 1385 } 1386 } 1387 /// Visit if-then-else 1388 void vITE(ITE& ite) { 1389 bool mustBeBool = false; 1390 if (ite.e_else() == NULL) { 1391 // this is an "if <cond> then <expr> endif" so the <expr> must be bool 1392 ite.e_else(constants().boollit(true)); 1393 mustBeBool = true; 1394 } 1395 Type tret = ite.e_else()->type(); 1396 std::vector<AnonVar*> anons; 1397 bool allpar = !(tret.isvar()); 1398 if (tret.isunknown()) { 1399 if (AnonVar* av = ite.e_else()->dyn_cast<AnonVar>()) { 1400 allpar = false; 1401 anons.push_back(av); 1402 } else { 1403 throw TypeError(_env, ite.e_else()->loc(), 1404 "cannot infer type of expression in `else' branch of conditional"); 1405 } 1406 } 1407 bool allpresent = !(tret.isopt()); 1408 bool varcond = false; 1409 for (int i = 0; i < ite.size(); i++) { 1410 Expression* eif = ite.e_if(i); 1411 Expression* ethen = ite.e_then(i); 1412 varcond = varcond || (eif->type() == Type::varbool()); 1413 if (eif->type() != Type::parbool() && eif->type() != Type::varbool()) 1414 throw TypeError( 1415 _env, eif->loc(), 1416 "expected bool conditional expression, got `" + eif->type().toString(_env) + "'"); 1417 if (eif->type().cv()) tret.cv(true); 1418 if (ethen->type().isunknown()) { 1419 if (AnonVar* av = ethen->dyn_cast<AnonVar>()) { 1420 allpar = false; 1421 anons.push_back(av); 1422 } else { 1423 throw TypeError(_env, ethen->loc(), 1424 "cannot infer type of expression in `then' branch of conditional"); 1425 } 1426 } else { 1427 if (tret.isbot() || tret.isunknown()) tret.bt(ethen->type().bt()); 1428 if (mustBeBool && 1429 (ethen->type().bt() != Type::BT_BOOL || ethen->type().dim() > 0 || 1430 ethen->type().st() != Type::ST_PLAIN || ethen->type().ot() != Type::OT_PRESENT)) { 1431 throw TypeError(_env, ite.loc(), 1432 std::string("conditional without `else' branch must have bool type, ") + 1433 "but `then' branch has type `" + ethen->type().toString(_env) + "'"); 1434 } 1435 if ((!ethen->type().isbot() && !Type::bt_subtype(ethen->type(), tret, true) && 1436 !Type::bt_subtype(tret, ethen->type(), true)) || 1437 ethen->type().st() != tret.st() || ethen->type().dim() != tret.dim()) { 1438 throw TypeError(_env, ethen->loc(), 1439 "type mismatch in branches of conditional. `then' branch has type `" + 1440 ethen->type().toString(_env) + "', but `else' branch has type `" + 1441 tret.toString(_env) + "'"); 1442 } 1443 if (Type::bt_subtype(tret, ethen->type(), true)) { 1444 tret.bt(ethen->type().bt()); 1445 } 1446 if (ethen->type().isvar()) allpar = false; 1447 if (ethen->type().isopt()) allpresent = false; 1448 if (ethen->type().cv()) tret.cv(true); 1449 } 1450 } 1451 Type tret_var(tret); 1452 tret_var.ti(Type::TI_VAR); 1453 for (unsigned int i = 0; i < anons.size(); i++) { 1454 anons[i]->type(tret_var); 1455 } 1456 for (int i = 0; i < ite.size(); i++) { 1457 ite.e_then(i, addCoercion(_env, _model, ite.e_then(i), tret)()); 1458 } 1459 ite.e_else(addCoercion(_env, _model, ite.e_else(), tret)()); 1460 /// TODO: perhaps extend flattener to array types, but for now throw an error 1461 if (varcond && tret.dim() > 0) 1462 throw TypeError(_env, ite.loc(), "conditional with var condition cannot have array type"); 1463 if (varcond || !allpar) tret.ti(Type::TI_VAR); 1464 if (!allpresent) tret.ot(Type::OT_OPTIONAL); 1465 ite.type(tret); 1466 } 1467 /// Visit binary operator 1468 void vBinOp(BinOp& bop) { 1469 std::vector<Expression*> args(2); 1470 args[0] = bop.lhs(); 1471 args[1] = bop.rhs(); 1472 if (FunctionI* fi = _model->matchFn(_env, bop.opToString(), args, true)) { 1473 bop.lhs(addCoercion(_env, _model, bop.lhs(), fi->argtype(_env, args, 0))()); 1474 bop.rhs(addCoercion(_env, _model, bop.rhs(), fi->argtype(_env, args, 1))()); 1475 args[0] = bop.lhs(); 1476 args[1] = bop.rhs(); 1477 Type ty = fi->rtype(_env, args, true); 1478 ty.cv(bop.lhs()->type().cv() || bop.rhs()->type().cv()); 1479 bop.type(ty); 1480 1481 if (fi->e()) 1482 bop.decl(fi); 1483 else 1484 bop.decl(NULL); 1485 } else { 1486 throw TypeError(_env, bop.loc(), 1487 std::string("type error in operator application for `") + 1488 bop.opToString().str() + 1489 "'. No matching operator found with left-hand side type `" + 1490 bop.lhs()->type().toString(_env) + "' and right-hand side type `" + 1491 bop.rhs()->type().toString(_env) + "'"); 1492 } 1493 } 1494 /// Visit unary operator 1495 void vUnOp(UnOp& uop) { 1496 std::vector<Expression*> args(1); 1497 args[0] = uop.e(); 1498 if (FunctionI* fi = _model->matchFn(_env, uop.opToString(), args, true)) { 1499 uop.e(addCoercion(_env, _model, uop.e(), fi->argtype(_env, args, 0))()); 1500 args[0] = uop.e(); 1501 Type ty = fi->rtype(_env, args, true); 1502 ty.cv(uop.e()->type().cv()); 1503 uop.type(ty); 1504 if (fi->e()) uop.decl(fi); 1505 } else { 1506 throw TypeError(_env, uop.loc(), 1507 std::string("type error in operator application for `") + 1508 uop.opToString().str() + "'. No matching operator found with type `" + 1509 uop.e()->type().toString(_env) + "'"); 1510 } 1511 } 1512 static std::string createEnumToStringName(Id* ident, std::string prefix) { 1513 std::string name = ident->str().str(); 1514 if (name[0] == '\'') { 1515 name = "'" + prefix + name.substr(1); 1516 } else { 1517 name = prefix + name; 1518 } 1519 return name; 1520 } 1521 1522 /// Visit call 1523 void vCall(Call& call) { 1524 std::vector<Expression*> args(call.n_args()); 1525 for (unsigned int i = static_cast<unsigned int>(args.size()); i--;) args[i] = call.arg(i); 1526 if (FunctionI* fi = _model->matchFn(_env, call.id(), args, true)) { 1527 bool cv = false; 1528 for (unsigned int i = 0; i < args.size(); i++) { 1529 if (Comprehension* c = call.arg(i)->dyn_cast<Comprehension>()) { 1530 Type t_before = c->e()->type(); 1531 Type t = fi->argtype(_env, args, i); 1532 t.dim(0); 1533 c->e(addCoercion(_env, _model, c->e(), t)()); 1534 Type t_after = c->e()->type(); 1535 if (t_before != t_after) { 1536 Type ct = c->type(); 1537 ct.bt(t_after.bt()); 1538 c->type(ct); 1539 } 1540 } else { 1541 args[i] = addCoercion(_env, _model, call.arg(i), fi->argtype(_env, args, i))(); 1542 call.arg(i, args[i]); 1543 } 1544 cv = cv || args[i]->type().cv(); 1545 } 1546 // Replace par enums with their string versions 1547 if (call.id() == "format" || call.id() == "show" || call.id() == "showDzn" || 1548 call.id() == "showJSON") { 1549 if (call.arg(call.n_args() - 1)->type().ispar()) { 1550 int enumId = call.arg(call.n_args() - 1)->type().enumId(); 1551 if (enumId != 0 && call.arg(call.n_args() - 1)->type().dim() != 0) { 1552 const std::vector<unsigned int>& enumIds = _env.getArrayEnum(enumId); 1553 enumId = enumIds[enumIds.size() - 1]; 1554 } 1555 if (enumId > 0) { 1556 VarDecl* enumDecl = _env.getEnum(enumId)->e(); 1557 if (enumDecl->e()) { 1558 Id* ti_id = _env.getEnum(enumId)->e()->id(); 1559 GCLock lock; 1560 std::vector<Expression*> args(3); 1561 args[0] = call.arg(call.n_args() - 1); 1562 if (args[0]->type().dim() > 1) { 1563 std::vector<Expression*> a1dargs(1); 1564 a1dargs[0] = args[0]; 1565 Call* array1d = new Call(Location().introduce(), ASTString("array1d"), a1dargs); 1566 Type array1dt = args[0]->type(); 1567 array1dt.dim(1); 1568 array1d->type(array1dt); 1569 args[0] = array1d; 1570 } 1571 args[1] = constants().boollit(call.id() == "showDzn"); 1572 args[2] = constants().boollit(call.id() == "showJSON"); 1573 ASTString enumName(createEnumToStringName(ti_id, "_toString_")); 1574 call.id(enumName); 1575 call.args(args); 1576 if (call.id() == "showDzn") { 1577 call.id(constants().ids.show); 1578 } 1579 fi = _model->matchFn(_env, &call, false); 1580 if (fi == NULL) { 1581 std::ostringstream oss; 1582 oss << "no function or predicate with this signature found: `"; 1583 oss << call.id() << "("; 1584 for (unsigned int i = 0; i < call.n_args(); i++) { 1585 oss << call.arg(i)->type().toString(_env); 1586 if (i < call.n_args() - 1) oss << ","; 1587 } 1588 oss << ")'"; 1589 throw TypeError(_env, call.loc(), oss.str()); 1590 } 1591 } 1592 } 1593 } 1594 } 1595 1596 // Set type and decl 1597 Type ty = fi->rtype(_env, args, true); 1598 ty.cv(cv); 1599 call.type(ty); 1600 call.decl(fi); 1601 } else { 1602 std::ostringstream oss; 1603 oss << "no function or predicate with this signature found: `"; 1604 oss << call.id() << "("; 1605 for (unsigned int i = 0; i < call.n_args(); i++) { 1606 oss << call.arg(i)->type().toString(_env); 1607 if (i < call.n_args() - 1) oss << ","; 1608 } 1609 oss << ")'"; 1610 throw TypeError(_env, call.loc(), oss.str()); 1611 } 1612 } 1613 /// Visit let 1614 void vLet(Let& let) { 1615 bool cv = false; 1616 bool isVar = false; 1617 for (unsigned int i = 0; i < let.let().size(); i++) { 1618 Expression* li = let.let()[i]; 1619 cv = cv || li->type().cv(); 1620 if (VarDecl* vdi = li->dyn_cast<VarDecl>()) { 1621 if (vdi->e() == NULL && vdi->type().is_set() && vdi->type().isvar() && 1622 vdi->ti()->domain() == NULL) { 1623 _typeErrors.push_back( 1624 TypeError(_env, vdi->loc(), 1625 "set element type for `" + vdi->id()->str().str() + "' is not finite")); 1626 } 1627 if (vdi->type().ispar() && vdi->e() == NULL) 1628 throw TypeError(_env, vdi->loc(), 1629 "let variable `" + vdi->id()->v().str() + "' must be initialised"); 1630 if (vdi->ti()->hasTiVariable()) { 1631 _typeErrors.push_back( 1632 TypeError(_env, vdi->loc(), 1633 "type-inst variables not allowed in type-inst for let variable `" + 1634 vdi->id()->str().str() + "'")); 1635 } 1636 let.let_orig()[i] = vdi->e(); 1637 } 1638 isVar |= li->type().isvar(); 1639 } 1640 Type ty = let.in()->type(); 1641 ty.cv(cv); 1642 if (isVar && ty.bt() == Type::BT_BOOL && ty.dim() == 0) ty.ti(Type::TI_VAR); 1643 let.type(ty); 1644 } 1645 /// Visit variable declaration 1646 void vVarDecl(VarDecl& vd) { 1647 if (ignoreVarDecl) { 1648 if (vd.e()) { 1649 Type vdt = vd.ti()->type(); 1650 Type vet = vd.e()->type(); 1651 if (vdt.enumId() != 0 && vdt.dim() > 0 && 1652 (vd.e()->isa<ArrayLit>() || vd.e()->isa<Comprehension>() || 1653 (vd.e()->isa<BinOp>() && vd.e()->cast<BinOp>()->op() == BOT_PLUSPLUS))) { 1654 // Special case: index sets of array literals and comprehensions automatically 1655 // coerce to any enum index set 1656 const std::vector<unsigned int>& enumIds = _env.getArrayEnum(vdt.enumId()); 1657 if (enumIds[enumIds.size() - 1] == 0) { 1658 vdt.enumId(0); 1659 } else { 1660 std::vector<unsigned int> nEnumIds(enumIds.size()); 1661 for (unsigned int i = 0; i < nEnumIds.size() - 1; i++) nEnumIds[i] = 0; 1662 nEnumIds[nEnumIds.size() - 1] = enumIds[enumIds.size() - 1]; 1663 vdt.enumId(_env.registerArrayEnum(nEnumIds)); 1664 } 1665 } else if (vd.ti()->isEnum() && vd.e()->isa<Call>()) { 1666 if (vd.e()->cast<Call>()->id() == "anon_enum") { 1667 vet.enumId(vdt.enumId()); 1668 } 1669 } 1670 1671 if (vd.type().isunknown()) { 1672 vd.ti()->type(vet); 1673 vd.type(vet); 1674 } else if (!_env.isSubtype(vet, vdt, true)) { 1675 if (vet == Type::bot(1) && vd.e()->isa<ArrayLit>() && 1676 vd.e()->cast<ArrayLit>()->size() == 0 && vdt.dim() != 0) { 1677 // this is okay: assigning an empty array (one-dimensional) to an array variable 1678 } else { 1679 _typeErrors.push_back(TypeError(_env, vd.e()->loc(), 1680 "initialisation value for `" + vd.id()->str().str() + 1681 "' has invalid type-inst: expected `" + 1682 vd.ti()->type().toString(_env) + "', actual `" + 1683 vd.e()->type().toString(_env) + "'")); 1684 } 1685 } else { 1686 vd.e(addCoercion(_env, _model, vd.e(), vd.ti()->type())()); 1687 } 1688 } else { 1689 assert(!vd.type().isunknown()); 1690 } 1691 } else { 1692 vd.type(vd.ti()->type()); 1693 vd.id()->type(vd.type()); 1694 } 1695 } 1696 /// Visit type inst 1697 void vTypeInst(TypeInst& ti) { 1698 Type tt = ti.type(); 1699 bool foundEnum = ti.ranges().size() > 0 && ti.domain() && ti.domain()->type().enumId() != 0; 1700 if (ti.ranges().size() > 0) { 1701 bool foundTIId = false; 1702 for (unsigned int i = 0; i < ti.ranges().size(); i++) { 1703 TypeInst* ri = ti.ranges()[i]; 1704 assert(ri != NULL); 1705 if (ri->type().cv()) tt.cv(true); 1706 if (ri->type().enumId() != 0) { 1707 foundEnum = true; 1708 } 1709 if (ri->type() == Type::top()) { 1710 // if (foundTIId) { 1711 // throw TypeError(_env,ri->loc(), 1712 // "only one type-inst variable allowed in array index"); 1713 // } else { 1714 foundTIId = true; 1715 // } 1716 } else if (ri->type() != Type::parint()) { 1717 assert(ri->isa<TypeInst>()); 1718 TypeInst* riti = ri->cast<TypeInst>(); 1719 if (riti->domain()) { 1720 throw TypeError(_env, ri->loc(), 1721 "array index set expression has invalid type, expected `set of int', " 1722 "actual `set of " + 1723 ri->type().toString(_env) + "'"); 1724 } else { 1725 throw TypeError(_env, ri->loc(), 1726 "cannot use `" + ri->type().toString(_env) + 1727 "' as array index set (did you mean `int'?)"); 1728 } 1729 } 1730 } 1731 tt.dim(foundTIId ? -1 : ti.ranges().size()); 1732 } 1733 if (ti.domain() && ti.domain()->type().cv()) tt.cv(true); 1734 if (ti.domain()) { 1735 if (TIId* tiid = ti.domain()->dyn_cast<TIId>()) { 1736 if (tiid->isEnum()) { 1737 tt.bt(Type::BT_INT); 1738 } 1739 } else { 1740 if (ti.domain()->type().ti() != Type::TI_PAR || ti.domain()->type().st() != Type::ST_SET) 1741 throw TypeError( 1742 _env, ti.domain()->loc(), 1743 "type-inst must be par set but is `" + ti.domain()->type().toString(_env) + "'"); 1744 if (ti.domain()->type().dim() != 0) 1745 throw TypeError(_env, ti.domain()->loc(), "type-inst cannot be an array"); 1746 } 1747 } 1748 if (tt.isunknown() && ti.domain()) { 1749 assert(ti.domain()); 1750 switch (ti.domain()->type().bt()) { 1751 case Type::BT_INT: 1752 case Type::BT_FLOAT: 1753 break; 1754 case Type::BT_BOT: { 1755 Type tidt = ti.domain()->type(); 1756 tidt.bt(Type::BT_INT); 1757 ti.domain()->type(tidt); 1758 } break; 1759 default: 1760 throw TypeError(_env, ti.domain()->loc(), "type-inst must be int or float"); 1761 } 1762 tt.bt(ti.domain()->type().bt()); 1763 tt.enumId(ti.domain()->type().enumId()); 1764 } else { 1765 // assert(ti.domain()==NULL || ti.domain()->isa<TIId>()); 1766 } 1767 if (foundEnum) { 1768 std::vector<unsigned int> enumIds(ti.ranges().size() + 1); 1769 for (unsigned int i = 0; i < ti.ranges().size(); i++) { 1770 enumIds[i] = ti.ranges()[i]->type().enumId(); 1771 } 1772 enumIds[ti.ranges().size()] = ti.domain() ? ti.domain()->type().enumId() : 0; 1773 int arrayEnumId = _env.registerArrayEnum(enumIds); 1774 tt.enumId(arrayEnumId); 1775 } 1776 1777 if (tt.st() == Type::ST_SET && tt.ti() == Type::TI_VAR && tt.bt() != Type::BT_INT && 1778 tt.bt() != Type::BT_TOP) 1779 throw TypeError(_env, ti.loc(), "var set element types other than `int' not allowed"); 1780 ti.type(tt); 1781 } 1782 void vTIId(TIId& id) {} 1783}; 1784 1785void typecheck(Env& env, Model* origModel, std::vector<TypeError>& typeErrors, 1786 bool ignoreUndefinedParameters, bool allowMultiAssignment, bool isFlatZinc) { 1787 Model* m; 1788 if (!isFlatZinc && origModel == env.model()) { 1789 // Combine all items into single model 1790 Model* combinedModel = new Model; 1791 class Combiner : public ItemVisitor { 1792 public: 1793 Model* m; 1794 Combiner(Model* m0) : m(m0) {} 1795 bool enter(Item* i) { 1796 if (!i->isa<IncludeI>()) m->addItem(i); 1797 return true; 1798 } 1799 } _combiner(combinedModel); 1800 iterItems(_combiner, origModel); 1801 env.envi().orig_model = origModel; 1802 env.envi().model = combinedModel; 1803 m = combinedModel; 1804 } else { 1805 m = origModel; 1806 } 1807 1808 // Topological sorting 1809 TopoSorter ts(m); 1810 1811 std::vector<FunctionI*> functionItems; 1812 std::vector<AssignI*> assignItems; 1813 Model* enumItems = new Model; 1814 1815 class TSVFuns : public ItemVisitor { 1816 public: 1817 EnvI& env; 1818 Model* model; 1819 std::vector<FunctionI*>& fis; 1820 TSVFuns(EnvI& env0, Model* model0, std::vector<FunctionI*>& fis0) 1821 : env(env0), model(model0), fis(fis0) {} 1822 void vFunctionI(FunctionI* i) { 1823 model->registerFn(env, i); 1824 fis.push_back(i); 1825 } 1826 } _tsvf(env.envi(), m, functionItems); 1827 iterItems(_tsvf, m); 1828 1829 class TSV0 : public ItemVisitor { 1830 public: 1831 EnvI& env; 1832 TopoSorter& ts; 1833 Model* model; 1834 bool hadSolveItem; 1835 std::vector<AssignI*>& ais; 1836 VarDeclI* objective; 1837 Model* enumis; 1838 TSV0(EnvI& env0, TopoSorter& ts0, Model* model0, std::vector<AssignI*>& ais0, Model* enumis0) 1839 : env(env0), 1840 ts(ts0), 1841 model(model0), 1842 hadSolveItem(false), 1843 ais(ais0), 1844 objective(NULL), 1845 enumis(enumis0) {} 1846 void vAssignI(AssignI* i) { ais.push_back(i); } 1847 void vVarDeclI(VarDeclI* i) { 1848 ts.add(env, i, true, enumis); 1849 // initialise new identifier counter to be larger than existing identifier 1850 if (i->e()->id()->idn() >= 0) { 1851 env.minId(i->e()->id()->idn()); 1852 } else if (i->e()->id()->v().beginsWith("X_INTRODUCED_") && i->e()->id()->v().endsWith("_")) { 1853 std::string numId = i->e()->id()->v().str().substr(std::string("X_INTRODUCED_").size()); 1854 if (numId.size() > 0) { 1855 numId = numId.substr(0, numId.size() - 1); 1856 if (numId.size() > 0) { 1857 int vId = -1; 1858 try { 1859 vId = std::stoi(numId); 1860 } catch (std::exception&) { 1861 } 1862 if (vId >= 0) env.minId(vId); 1863 } 1864 } 1865 } 1866 } 1867 void vSolveI(SolveI* si) { 1868 if (hadSolveItem) throw TypeError(env, si->loc(), "Only one solve item allowed"); 1869 hadSolveItem = true; 1870 if (si->e()) { 1871 GCLock lock; 1872 TypeInst* ti = new TypeInst(Location().introduce(), Type()); 1873 VarDecl* obj = new VarDecl(Location().introduce(), ti, "_objective", si->e()); 1874 si->e(obj->id()); 1875 objective = new VarDeclI(Location().introduce(), obj); 1876 } 1877 } 1878 } _tsv0(env.envi(), ts, m, assignItems, enumItems); 1879 iterItems(_tsv0, m); 1880 if (_tsv0.objective) { 1881 m->addItem(_tsv0.objective); 1882 ts.add(env.envi(), _tsv0.objective, true, enumItems); 1883 } 1884 1885 for (unsigned int i = 0; i < enumItems->size(); i++) { 1886 if (AssignI* ai = (*enumItems)[i]->dyn_cast<AssignI>()) { 1887 assignItems.push_back(ai); 1888 } else if (VarDeclI* vdi = (*enumItems)[i]->dyn_cast<VarDeclI>()) { 1889 m->addItem(vdi); 1890 ts.add(env.envi(), vdi, false, enumItems); 1891 } else { 1892 FunctionI* fi = (*enumItems)[i]->dyn_cast<FunctionI>(); 1893 m->addItem(fi); 1894 m->registerFn(env.envi(), fi); 1895 functionItems.push_back(fi); 1896 } 1897 } 1898 1899 Model* enumItems2 = new Model; 1900 1901 for (unsigned int i = 0; i < assignItems.size(); i++) { 1902 AssignI* ai = assignItems[i]; 1903 VarDecl* vd = NULL; 1904 if (env.envi().ignoreUnknownIds) { 1905 try { 1906 vd = ts.get(env.envi(), ai->id(), ai->loc()); 1907 } catch (TypeError&) { 1908 } 1909 } else { 1910 vd = ts.get(env.envi(), ai->id(), ai->loc()); 1911 } 1912 if (vd) { 1913 if (vd->e()) { 1914 if (allowMultiAssignment) { 1915 GCLock lock; 1916 m->addItem(new ConstraintI( 1917 ai->loc(), 1918 new BinOp(ai->loc(), new Id(Location().introduce(), ai->id(), vd), BOT_EQ, ai->e()))); 1919 } else { 1920 throw TypeError(env.envi(), ai->loc(), "multiple assignment to the same variable"); 1921 } 1922 } else { 1923 vd->e(ai->e()); 1924 vd->ann().add(constants().ann.rhs_from_assignment); 1925 if (vd->ti()->isEnum()) { 1926 GCLock lock; 1927 ASTString name(createEnumToStringName(vd->id(), "_enum_to_string_")); 1928 VarDecl* vd_enum = ts.get(env.envi(), name, vd->loc()); 1929 if (vd_enum->e()) 1930 throw TypeError(env.envi(), ai->loc(), "multiple definition of the same enum"); 1931 AssignI* ai_enum = 1932 createEnumMapper(env.envi(), m, vd->ti()->type().enumId(), vd, vd_enum, enumItems2); 1933 if (ai_enum) { 1934 vd_enum->e(ai_enum->e()); 1935 ai_enum->remove(); 1936 } 1937 } 1938 } 1939 } 1940 ai->remove(); 1941 } 1942 1943 for (unsigned int i = 0; i < enumItems2->size(); i++) { 1944 if (VarDeclI* vdi = (*enumItems2)[i]->dyn_cast<VarDeclI>()) { 1945 m->addItem(vdi); 1946 ts.add(env.envi(), vdi, false, enumItems); 1947 } else { 1948 FunctionI* fi = (*enumItems2)[i]->cast<FunctionI>(); 1949 m->addItem(fi); 1950 m->registerFn(env.envi(), fi); 1951 functionItems.push_back(fi); 1952 } 1953 } 1954 1955 delete enumItems; 1956 delete enumItems2; 1957 1958 class TSV1 : public ItemVisitor { 1959 public: 1960 EnvI& env; 1961 TopoSorter& ts; 1962 TSV1(EnvI& env0, TopoSorter& ts0) : env(env0), ts(ts0) {} 1963 void vVarDeclI(VarDeclI* i) { ts.run(env, i->e()); } 1964 void vAssignI(AssignI* i) {} 1965 void vConstraintI(ConstraintI* i) { ts.run(env, i->e()); } 1966 void vSolveI(SolveI* i) { 1967 for (ExpressionSetIter it = i->ann().begin(); it != i->ann().end(); ++it) ts.run(env, *it); 1968 ts.run(env, i->e()); 1969 } 1970 void vOutputI(OutputI* i) { ts.run(env, i->e()); } 1971 void vFunctionI(FunctionI* fi) { 1972 ts.run(env, fi->ti()); 1973 for (unsigned int i = 0; i < fi->params().size(); i++) ts.run(env, fi->params()[i]); 1974 for (ExpressionSetIter it = fi->ann().begin(); it != fi->ann().end(); ++it) ts.run(env, *it); 1975 ts.scopes.push(false); 1976 for (unsigned int i = 0; i < fi->params().size(); i++) ts.scopes.add(env, fi->params()[i]); 1977 ts.run(env, fi->e()); 1978 ts.scopes.pop(); 1979 } 1980 } _tsv1(env.envi(), ts); 1981 iterItems(_tsv1, m); 1982 1983 m->sortFn(); 1984 1985 { 1986 struct SortByPayload { 1987 bool operator()(Item* i0, Item* i1) { 1988 if (i0->isa<IncludeI>()) return !i1->isa<IncludeI>(); 1989 if (VarDeclI* vdi0 = i0->dyn_cast<VarDeclI>()) { 1990 if (VarDeclI* vdi1 = i1->dyn_cast<VarDeclI>()) { 1991 return vdi0->e()->payload() < vdi1->e()->payload(); 1992 } else { 1993 return !i1->isa<IncludeI>(); 1994 } 1995 } 1996 return false; 1997 } 1998 } _sbp; 1999 2000 std::stable_sort(m->begin(), m->end(), _sbp); 2001 } 2002 2003 { 2004 Typer<false> ty(env.envi(), m, typeErrors, ignoreUndefinedParameters); 2005 BottomUpIterator<Typer<false> > bu_ty(ty); 2006 for (unsigned int i = 0; i < ts.decls.size(); i++) { 2007 ts.decls[i]->payload(0); 2008 bu_ty.run(ts.decls[i]->ti()); 2009 ty.vVarDecl(*ts.decls[i]); 2010 } 2011 for (unsigned int i = 0; i < functionItems.size(); i++) { 2012 bu_ty.run(functionItems[i]->ti()); 2013 for (unsigned int j = 0; j < functionItems[i]->params().size(); j++) 2014 bu_ty.run(functionItems[i]->params()[j]); 2015 } 2016 } 2017 2018 m->fixFnMap(); 2019 2020 { 2021 Typer<true> ty(env.envi(), m, typeErrors, ignoreUndefinedParameters); 2022 BottomUpIterator<Typer<true> > bu_ty(ty); 2023 2024 class TSV2 : public ItemVisitor { 2025 public: 2026 EnvI& env; 2027 Model* m; 2028 BottomUpIterator<Typer<true> >& bu_ty; 2029 std::vector<TypeError>& _typeErrors; 2030 TSV2(EnvI& env0, Model* m0, BottomUpIterator<Typer<true> >& b, 2031 std::vector<TypeError>& typeErrors) 2032 : env(env0), m(m0), bu_ty(b), _typeErrors(typeErrors) {} 2033 void vVarDeclI(VarDeclI* i) { 2034 bu_ty.run(i->e()); 2035 if (i->e()->ti()->hasTiVariable()) { 2036 _typeErrors.push_back(TypeError(env, i->e()->loc(), 2037 "type-inst variables not allowed in type-inst for `" + 2038 i->e()->id()->str().str() + "'")); 2039 } 2040 VarDecl* vdi = i->e(); 2041 if (vdi->e() == NULL && vdi->type().is_set() && vdi->type().isvar() && 2042 vdi->ti()->domain() == NULL) { 2043 _typeErrors.push_back( 2044 TypeError(env, vdi->loc(), 2045 "set element type for `" + vdi->id()->str().str() + "' is not finite")); 2046 } 2047 if (i->e()->ann().contains(constants().ann.output_only) && vdi->e()->type().isvar()) { 2048 _typeErrors.push_back( 2049 TypeError(env, vdi->loc(), "variables annotated with ::output_only must be par")); 2050 } 2051 } 2052 void vAssignI(AssignI* i) { 2053 bu_ty.run(i->e()); 2054 if (!env.isSubtype(i->e()->type(), i->decl()->ti()->type(), true)) { 2055 _typeErrors.push_back(TypeError(env, i->loc(), 2056 "assignment value for `" + i->decl()->id()->str().str() + 2057 "' has invalid type-inst: expected `" + 2058 i->decl()->ti()->type().toString(env) + 2059 "', actual `" + i->e()->type().toString(env) + "'")); 2060 // Assign to "true" constant to avoid generating further errors that the parameter 2061 // is undefined 2062 i->decl()->e(constants().lit_true); 2063 } 2064 } 2065 void vConstraintI(ConstraintI* i) { 2066 bu_ty.run(i->e()); 2067 if (!env.isSubtype(i->e()->type(), Type::varbool(), true)) 2068 throw TypeError(env, i->loc(), 2069 "invalid type of constraint, expected `" + Type::varbool().toString(env) + 2070 "', actual `" + i->e()->type().toString(env) + "'"); 2071 } 2072 void vSolveI(SolveI* i) { 2073 for (ExpressionSetIter it = i->ann().begin(); it != i->ann().end(); ++it) { 2074 bu_ty.run(*it); 2075 if (!(*it)->type().isann()) 2076 throw TypeError(env, (*it)->loc(), 2077 "expected annotation, got `" + (*it)->type().toString(env) + "'"); 2078 } 2079 bu_ty.run(i->e()); 2080 if (i->e()) { 2081 Type et = i->e()->type(); 2082 2083 bool needOptCoercion = et.isopt() && et.isint(); 2084 if (needOptCoercion) { 2085 et.ot(Type::OT_PRESENT); 2086 } 2087 2088 if (!(env.isSubtype(et, Type::varint(), true) || 2089 env.isSubtype(et, Type::varfloat(), true))) 2090 throw TypeError(env, i->e()->loc(), 2091 "objective has invalid type, expected int or float, actual `" + 2092 et.toString(env) + "'"); 2093 2094 if (needOptCoercion) { 2095 GCLock lock; 2096 std::vector<Expression*> args(2); 2097 args[0] = i->e(); 2098 args[1] = constants().boollit(i->st() == SolveI::ST_MAX); 2099 Call* c = new Call(Location().introduce(), ASTString("objective_deopt_"), args); 2100 c->decl(env.model->matchFn(env, c, false)); 2101 assert(c->decl()); 2102 c->type(et); 2103 i->e(c); 2104 } 2105 } 2106 } 2107 void vOutputI(OutputI* i) { 2108 bu_ty.run(i->e()); 2109 if (i->e()->type() != Type::parstring(1) && i->e()->type() != Type::bot(1)) 2110 throw TypeError(env, i->e()->loc(), 2111 "invalid type in output item, expected `" + 2112 Type::parstring(1).toString(env) + "', actual `" + 2113 i->e()->type().toString(env) + "'"); 2114 } 2115 void vFunctionI(FunctionI* i) { 2116 for (ExpressionSetIter it = i->ann().begin(); it != i->ann().end(); ++it) { 2117 bu_ty.run(*it); 2118 if (!(*it)->type().isann()) 2119 throw TypeError(env, (*it)->loc(), 2120 "expected annotation, got `" + (*it)->type().toString(env) + "'"); 2121 } 2122 bu_ty.run(i->ti()); 2123 bu_ty.run(i->e()); 2124 if (i->e() && !env.isSubtype(i->e()->type(), i->ti()->type(), true)) 2125 throw TypeError(env, i->e()->loc(), 2126 "return type of function does not match body, declared type is `" + 2127 i->ti()->type().toString(env) + "', body type is `" + 2128 i->e()->type().toString(env) + "'"); 2129 if (i->e() && i->e()->type().ispar() && i->ti()->type().isvar()) { 2130 // this is a par function declared as var, so change declared return type 2131 Type i_t = i->ti()->type(); 2132 i_t.ti(Type::TI_PAR); 2133 i->ti()->type(i_t); 2134 } 2135 if (i->e()) i->e(addCoercion(env, m, i->e(), i->ti()->type())()); 2136 } 2137 } _tsv2(env.envi(), m, bu_ty, typeErrors); 2138 iterItems(_tsv2, m); 2139 } 2140 2141 class TSV3 : public ItemVisitor { 2142 public: 2143 EnvI& env; 2144 Model* m; 2145 OutputI* outputItem; 2146 TSV3(EnvI& env0, Model* m0) : env(env0), m(m0), outputItem(NULL) {} 2147 void vAssignI(AssignI* i) { i->decl()->e(addCoercion(env, m, i->e(), i->decl()->type())()); } 2148 void vOutputI(OutputI* oi) { 2149 if (outputItem == NULL) { 2150 outputItem = oi; 2151 } else { 2152 GCLock lock; 2153 BinOp* bo = new BinOp(Location().introduce(), outputItem->e(), BOT_PLUSPLUS, oi->e()); 2154 bo->type(Type::parstring(1)); 2155 outputItem->e(bo); 2156 oi->remove(); 2157 m->setOutputItem(outputItem); 2158 } 2159 } 2160 } _tsv3(env.envi(), m); 2161 if (typeErrors.empty()) { 2162 iterItems(_tsv3, m); 2163 } 2164 2165 try { 2166 m->checkFnOverloading(env.envi()); 2167 } catch (TypeError& e) { 2168 typeErrors.push_back(e); 2169 } 2170 2171 for (unsigned int i = 0; i < ts.decls.size(); i++) { 2172 if (ts.decls[i]->toplevel() && ts.decls[i]->type().ispar() && !ts.decls[i]->type().isann() && 2173 ts.decls[i]->e() == NULL) { 2174 if (ts.decls[i]->type().isopt() && ts.decls[i]->type().dim() == 0) { 2175 ts.decls[i]->e(constants().absent); 2176 } else if (!ignoreUndefinedParameters) { 2177 typeErrors.push_back( 2178 TypeError(env.envi(), ts.decls[i]->loc(), 2179 " symbol error: variable `" + ts.decls[i]->id()->str().str() + 2180 "' must be defined (did you forget to specify a data file?)")); 2181 } 2182 } 2183 if (ts.decls[i]->ti()->isEnum()) { 2184 ts.decls[i]->ti()->setIsEnum(false); 2185 Type vdt = ts.decls[i]->ti()->type(); 2186 vdt.enumId(0); 2187 ts.decls[i]->ti()->type(vdt); 2188 } 2189 } 2190 2191 for (auto vd_k : env.envi().checkVars) { 2192 try { 2193 VarDecl* vd = 2194 ts.get(env.envi(), vd_k()->cast<VarDecl>()->id()->str(), vd_k()->cast<VarDecl>()->loc()); 2195 vd->ann().add(constants().ann.mzn_check_var); 2196 if (vd->type().enumId() != 0) { 2197 GCLock lock; 2198 int enumId = vd->type().enumId(); 2199 if (vd->type().dim() > 0) { 2200 const std::vector<unsigned int>& arrayEnumIds = 2201 env.envi().getArrayEnum(vd->type().enumId()); 2202 enumId = arrayEnumIds[arrayEnumIds.size() - 1]; 2203 } 2204 if (enumId > 0) { 2205 std::vector<Expression*> args({env.envi().getEnum(enumId)->e()->id()}); 2206 Call* checkEnum = 2207 new Call(Location().introduce(), constants().ann.mzn_check_enum_var, args); 2208 checkEnum->type(Type::ann()); 2209 checkEnum->decl(env.envi().model->matchFn(env.envi(), checkEnum, false)); 2210 vd->ann().add(checkEnum); 2211 } 2212 } 2213 Type vdktype = vd_k()->type(); 2214 vdktype.ti(Type::TI_VAR); 2215 if (!vd_k()->type().isSubtypeOf(vd->type(), false)) { 2216 GCLock lock; 2217 2218 typeErrors.push_back(TypeError(env.envi(), vd->loc(), 2219 "Solution checker requires `" + vd->id()->str().str() + 2220 "' to be of type `" + vdktype.toString(env.envi()) + 2221 "'")); 2222 } 2223 } catch (TypeError& e) { 2224 typeErrors.push_back( 2225 TypeError(env.envi(), e.loc(), e.msg() + " (required by solution checker model)")); 2226 } 2227 } 2228} 2229 2230void typecheck(Env& env, Model* m, AssignI* ai) { 2231 std::vector<TypeError> typeErrors; 2232 Typer<true> ty(env.envi(), m, typeErrors, false); 2233 BottomUpIterator<Typer<true> > bu_ty(ty); 2234 bu_ty.run(ai->e()); 2235 if (!typeErrors.empty()) { 2236 throw typeErrors[0]; 2237 } 2238 if (!env.envi().isSubtype(ai->e()->type(), ai->decl()->ti()->type(), true)) { 2239 throw TypeError(env.envi(), ai->e()->loc(), 2240 "assignment value for `" + ai->decl()->id()->str().str() + 2241 "' has invalid type-inst: expected `" + 2242 ai->decl()->ti()->type().toString(env.envi()) + "', actual `" + 2243 ai->e()->type().toString(env.envi()) + "'"); 2244 } 2245} 2246 2247void output_var_desc_json(Env& env, VarDecl* vd, std::ostream& os, bool extra = false) { 2248 os << " \"" << *vd->id() << "\" : {"; 2249 os << "\"type\" : "; 2250 switch (vd->type().bt()) { 2251 case Type::BT_INT: 2252 os << "\"int\""; 2253 break; 2254 case Type::BT_BOOL: 2255 os << "\"bool\""; 2256 break; 2257 case Type::BT_FLOAT: 2258 os << "\"float\""; 2259 break; 2260 case Type::BT_STRING: 2261 os << "\"string\""; 2262 break; 2263 case Type::BT_ANN: 2264 os << "\"ann\""; 2265 break; 2266 default: 2267 os << "\"?\""; 2268 break; 2269 } 2270 if (vd->type().ot() == Type::OT_OPTIONAL) { 2271 os << ", \"optional\" : true"; 2272 } 2273 if (vd->type().st() == Type::ST_SET) { 2274 os << ", \"set\" : true"; 2275 } 2276 if (vd->type().dim() > 0) { 2277 os << ", \"dim\" : " << vd->type().dim(); 2278 2279 if (extra) { 2280 os << ", \"dims\" : ["; 2281 bool had_dim = false; 2282 ASTExprVec<TypeInst> ranges = vd->ti()->ranges(); 2283 for (int i = 0; i < static_cast<int>(ranges.size()); i++) { 2284 if (ranges[i]->type().enumId() > 0) { 2285 os << (had_dim ? "," : "") << "\"" 2286 << *env.envi().getEnum(ranges[i]->type().enumId())->e()->id() << "\""; 2287 } else { 2288 os << (had_dim ? "," : "") << "\"int\""; 2289 } 2290 had_dim = true; 2291 } 2292 os << "]"; 2293 2294 if (vd->type().enumId() > 0) { 2295 const std::vector<unsigned int>& enumIds = env.envi().getArrayEnum(vd->type().enumId()); 2296 if (enumIds.back() > 0) { 2297 os << ", \"enum_type\" : \"" << *env.envi().getEnum(enumIds.back())->e()->id() << "\""; 2298 } 2299 } 2300 } 2301 2302 } else { 2303 if (extra) { 2304 if (vd->type().enumId() > 0) { 2305 os << ", \"enum_type\" : \"" << *env.envi().getEnum(vd->type().enumId())->e()->id() << "\""; 2306 } 2307 } 2308 } 2309 os << "}"; 2310} 2311 2312void output_model_variable_types(Env& env, Model* m, std::ostream& os) { 2313 class VInfVisitor : public ItemVisitor { 2314 public: 2315 Env& env; 2316 bool had_var; 2317 bool had_enum; 2318 std::ostringstream oss_vars; 2319 std::ostringstream oss_enums; 2320 VInfVisitor(Env& env0) : env(env0), had_var(false), had_enum(false) {} 2321 bool enter(Item* i) { 2322 if (IncludeI* ii = i->dyn_cast<IncludeI>()) { 2323 std::string prefix = 2324 ii->m()->filepath().str().substr(0, ii->m()->filepath().size() - ii->f().size()); 2325 return (prefix.empty() || prefix == "./"); 2326 } 2327 return true; 2328 } 2329 void vVarDeclI(VarDeclI* vdi) { 2330 if (!vdi->e()->type().isann() && !vdi->e()->ti()->isEnum()) { 2331 if (had_var) oss_vars << ",\n"; 2332 output_var_desc_json(env, vdi->e(), oss_vars, true); 2333 had_var = true; 2334 } else if (vdi->e()->type().st() == Type::ST_SET && vdi->e()->type().enumId() != 0 && 2335 !vdi->e()->type().isann()) { 2336 if (had_enum) oss_enums << ", "; 2337 oss_enums << "\"" << *env.envi().getEnum(vdi->e()->type().enumId())->e()->id() << "\""; 2338 had_enum = true; 2339 } 2340 } 2341 } _vinf(env); 2342 iterItems(_vinf, m); 2343 os << "{\"var_types\": {"; 2344 os << "\n \"vars\": {\n" << _vinf.oss_vars.str() << "\n },"; 2345 os << "\n \"enums\": [" << _vinf.oss_enums.str() << "]\n"; 2346 os << "}}\n"; 2347} 2348 2349void output_model_interface(Env& env, Model* m, std::ostream& os) { 2350 class IfcVisitor : public ItemVisitor { 2351 public: 2352 Env& env; 2353 bool had_input; 2354 bool had_output; 2355 bool had_add_to_output = false; 2356 std::ostringstream oss_input; 2357 std::ostringstream oss_output; 2358 std::string method; 2359 IfcVisitor(Env& env0) : env(env0), had_input(false), had_output(false), method("sat") {} 2360 bool enter(Item* i) { 2361 if (IncludeI* ii = i->dyn_cast<IncludeI>()) { 2362 std::string prefix = 2363 ii->m()->filepath().str().substr(0, ii->m()->filepath().size() - ii->f().size()); 2364 return (prefix.empty() || prefix == "./"); 2365 } 2366 return true; 2367 } 2368 void vVarDeclI(VarDeclI* vdi) { 2369 VarDecl* vd = vdi->e(); 2370 if (vd->type().ispar() && !vd->type().isann() && 2371 (vd->e() == NULL || vd->e() == constants().absent)) { 2372 if (had_input) oss_input << ",\n"; 2373 output_var_desc_json(env, vd, oss_input); 2374 had_input = true; 2375 } else { 2376 bool process_var = false; 2377 if (vd->ann().contains(constants().ann.add_to_output)) { 2378 if (!had_add_to_output) { 2379 oss_output.str(""); 2380 had_output = false; 2381 } 2382 had_add_to_output = true; 2383 process_var = true; 2384 } else if (!had_add_to_output) { 2385 process_var = 2386 vd->type().isvar() && 2387 (vd->e() == NULL || vd->ann().contains(constants().ann.rhs_from_assignment)); 2388 } 2389 if (process_var) { 2390 if (had_output) { 2391 oss_output << ",\n"; 2392 } 2393 output_var_desc_json(env, vd, oss_output); 2394 had_output = true; 2395 } 2396 } 2397 } 2398 void vSolveI(SolveI* si) { 2399 switch (si->st()) { 2400 case SolveI::ST_MIN: 2401 method = "min"; 2402 break; 2403 case SolveI::ST_MAX: 2404 method = "max"; 2405 break; 2406 case SolveI::ST_SAT: 2407 method = "sat"; 2408 break; 2409 } 2410 } 2411 } _ifc(env); 2412 iterItems(_ifc, m); 2413 os << "{\n \"input\" : {\n" 2414 << _ifc.oss_input.str() << "\n },\n \"output\" : {\n" 2415 << _ifc.oss_output.str() << "\n }"; 2416 os << ",\n \"method\": \""; 2417 os << _ifc.method; 2418 os << "\""; 2419 os << "\n}\n"; 2420} 2421 2422} // namespace MiniZinc