ct_common
1.0.1
Common library for combinatorial testing
|
00001 //===----- ct_common/file_parse/assembler.cpp -------------------*- C++ -*-===// 00002 // 00003 // The ct_common Library 00004 // 00005 // This file is distributed under the MIT license. See LICENSE for details. 00006 // 00007 //===----------------------------------------------------------------------===// 00008 // 00009 // This file contains the function definitions of class Assembler 00010 // 00011 //===----------------------------------------------------------------------===// 00012 00013 #include <algorithm> 00014 #include <exception> 00015 #include <cstdlib> 00016 #include <sstream> 00017 #include <cmath> 00018 #include <ct_common/file_parse/assembler.h> 00019 #include <ct_common/common/seed_tuple.h> 00020 #include <ct_common/common/seed_constraint.h> 00021 00022 using namespace ct::common; 00023 00024 Assembler::Assembler(void) { 00025 this->default_precision_ = 0; 00026 } 00027 00028 Assembler::Assembler(const Assembler &from) { 00029 this->default_precision_ = from.default_precision_; 00030 this->err_logger_ = from.err_logger_; 00031 this->stored_invalidations_ = from.stored_invalidations_; 00032 } 00033 00034 Assembler::~Assembler(void) { 00035 } 00036 00037 const Assembler &Assembler::operator =(const Assembler &right) { 00038 this->default_precision_ = right.default_precision_; 00039 this->err_logger_ = right.err_logger_; 00040 this->stored_invalidations_ = right.stored_invalidations_; 00041 return (*this); 00042 } 00043 00044 void Assembler::reportError(const std::string &str) { 00045 if (this->err_logger_.get()) { 00046 this->err_logger_->reportError(str); 00047 } 00048 } 00049 00050 void Assembler::reportWarning(const std::string &str) { 00051 if (this->err_logger_.get()) { 00052 this->err_logger_->reportWarning(str); 00053 } 00054 } 00055 00056 std::size_t Assembler::numErrs(void) const { 00057 if (this->err_logger_.get()) { 00058 return this->err_logger_->numErrs(); 00059 } 00060 return 0; 00061 } 00062 00063 std::size_t Assembler::numWarnings(void) const { 00064 if (this->err_logger_.get()) { 00065 return this->err_logger_->numWarnings(); 00066 } 00067 return 0; 00068 } 00069 00070 ParamSpec *Assembler::asm_paramspec( 00071 const std::string &type, 00072 const std::string &identifier, 00073 const std::vector<boost::shared_ptr<TreeNode> > &vals) { 00074 ParamSpec *tmp_return; 00075 if (type == "int") { 00076 tmp_return = new ParamSpec_Int(); 00077 } else if (type == "double") { 00078 tmp_return = new ParamSpec_Double(); 00079 } else if (type == "string") { 00080 tmp_return = new ParamSpec_String(); 00081 } else if (type == "bool") { 00082 tmp_return = new ParamSpec_Bool(); 00083 } else { 00084 CT_EXCEPTION("unrecognized parameter type"); 00085 return 0; 00086 } 00087 tmp_return->set_param_name(identifier); 00088 std::vector<std::string> str_vals; 00089 if (TYPE_CHECK(tmp_return, ParamSpec_Bool*)) { 00090 if (vals.size() != 2 || 00091 !TYPE_CHECK(vals[0].get(), Constraint_L_CBool*) || 00092 !TYPE_CHECK(vals[1].get(), Constraint_L_CBool*) || 00093 dynamic_cast<Constraint_L_CBool*>(vals[0].get())->get_value() != true || 00094 dynamic_cast<Constraint_L_CBool*>(vals[1].get())->get_value() != false) { 00095 this->reportWarning("values for boolean parameters are neglected, possible format is:"); 00096 this->reportWarning("bool <param>;"); 00097 this->reportWarning("bool <param>: true, false;"); 00098 } 00099 } else { 00100 for (std::size_t i = 0; i < vals.size(); ++i) { 00101 if (TYPE_CHECK(tmp_return, ParamSpec_Int*) && 00102 TYPE_CHECK(vals[i].get(), Exp_S_CString*)) { 00103 this->reportWarning( 00104 std::string("warning: forcing string value ") + vals[i]->get_str_value() 00105 + " as integer for parameter " + tmp_return->get_param_name()); 00106 } 00107 if (TYPE_CHECK(tmp_return, ParamSpec_Int*) && 00108 TYPE_CHECK(vals[i].get(), Exp_A_CDouble*)) { 00109 this->reportWarning( 00110 std::string("warning: forcing double value ") + vals[i]->get_str_value() 00111 + " as integer for parameter " + tmp_return->get_param_name()); 00112 } 00113 if (TYPE_CHECK(tmp_return, ParamSpec_Double*) && 00114 TYPE_CHECK(vals[i].get(), Exp_S_CString*)) { 00115 this->reportWarning( 00116 std::string("warning: forcing string value ") + vals[i]->get_str_value() 00117 + " as double for parameter " + tmp_return->get_param_name()); 00118 } 00119 if (TYPE_CHECK(tmp_return, ParamSpec_String*) && 00120 TYPE_CHECK(vals[i].get(), Exp_A_CInt*)) { 00121 this->reportWarning( 00122 std::string("warning: forcing integer value ") + vals[i]->get_str_value() 00123 + " as string for parameter " + tmp_return->get_param_name()); 00124 } 00125 if (TYPE_CHECK(tmp_return, ParamSpec_String*) && 00126 TYPE_CHECK(vals[i].get(), Exp_A_CDouble*)) { 00127 this->reportWarning( 00128 std::string("warning: forcing double value ") + vals[i]->get_str_value() 00129 + " as string for parameter " + tmp_return->get_param_name()); 00130 } 00131 str_vals.push_back(vals[i]->get_str_value()); 00132 } 00133 } 00134 tmp_return->set_values(str_vals); 00135 return tmp_return; 00136 } 00137 00138 ParamSpec *Assembler::asm_paramspec( 00139 const std::string &type, 00140 const std::string &identifier, 00141 const std::vector<std::pair<boost::shared_ptr<TreeNode>, boost::shared_ptr<TreeNode> > > &auto_value_specs) { 00142 ParamSpec *tmp_return; 00143 if (type == "int") { 00144 tmp_return = new ParamSpec_Int(); 00145 } else if (type == "double") { 00146 tmp_return = new ParamSpec_Double(); 00147 } else if (type == "string") { 00148 tmp_return = new ParamSpec_String(); 00149 } else if (type == "bool") { 00150 tmp_return = new ParamSpec_Bool(); 00151 } else { 00152 CT_EXCEPTION("unrecognized parameter type"); 00153 return 0; 00154 } 00155 if (auto_value_specs.size() == 0) { 00156 this->reportWarning(std::string("the auto value specs for parameter ") + identifier + " is empty"); 00157 } else { 00158 boost::shared_ptr<Constraint_L_CBool> last_cond = boost::dynamic_pointer_cast<Constraint_L_CBool>(auto_value_specs.back().first); 00159 if (!last_cond || last_cond->get_value() != true) { 00160 this->reportWarning(std::string("the last condition for auto parameter ") + identifier + " is not a constant true. This may cause errors if the specified conditions do not cover all the cases. Consider using a \"default\" or \"true\"."); 00161 } 00162 } 00163 00164 tmp_return->set_auto(true); 00165 tmp_return->set_param_name(identifier); 00166 tmp_return->auto_value_specs() = auto_value_specs; 00167 return tmp_return; 00168 } 00169 00170 00171 void attach_strengths_core( 00172 const std::vector<std::size_t> &pid_list, 00173 std::vector<std::vector<std::size_t> > &strengths, 00174 std::vector<std::size_t> &stack, 00175 std::size_t strength, 00176 std::size_t depth) { 00177 if (depth == strength) { 00178 std::vector<std::size_t> new_strength; 00179 for (std::size_t i = 0; i < stack.size(); ++i) { 00180 new_strength.push_back(pid_list[stack[i]]); 00181 } 00182 strengths.push_back(new_strength); 00183 return; 00184 } 00185 std::size_t start_point = 0; 00186 if (depth > 0) { 00187 start_point = stack[depth-1]+1; 00188 } 00189 for (std::size_t i = start_point; i < pid_list.size(); ++i) { 00190 stack[depth] = i; 00191 attach_strengths_core(pid_list, strengths, stack, strength, depth+1); 00192 } 00193 } 00194 00195 void Assembler::attach_default_strengths( 00196 const std::vector<boost::shared_ptr<ParamSpec> > ¶m_specs, 00197 std::vector<ct::common::Strength> &strengths, 00198 std::size_t strength) { 00199 // compute the parameter id list 00200 std::vector<std::size_t> pid_list; 00201 for (std::size_t i = 0; i < param_specs.size(); ++i) { 00202 if (!param_specs[i]->is_auto() && !param_specs[i]->is_aux()) { 00203 pid_list.push_back(i); 00204 } 00205 } 00206 // generate the strengths 00207 for (std::size_t i = 0; i < pid_list.size(); ++i) { 00208 if (param_specs[pid_list[i]]->is_auto()) { 00209 CT_EXCEPTION("auto parameters should never be included in any covering strength"); 00210 return; 00211 } 00212 } 00213 if (pid_list.size() < strength) { 00214 CT_EXCEPTION("the parameter list is smaller than the strength"); 00215 return; 00216 } 00217 Strength new_strength; 00218 new_strength.first = pid_list; 00219 new_strength.second = strength; 00220 strengths.push_back(new_strength); 00221 } 00222 00223 void Assembler::attach_strengths( 00224 const std::vector<boost::shared_ptr<ParamSpec> > ¶m_specs, 00225 const std::vector<std::string> &identifiers, 00226 std::vector<ct::common::Strength> &strengths, 00227 std::size_t strength) { 00228 // compute the parameter id list 00229 std::vector<std::size_t> pid_list; 00230 for (std::size_t i = 0; i < identifiers.size(); ++i) { 00231 if (identifiers[i] == "default") { 00232 for (std::size_t j = 0; j < param_specs.size(); ++j) { 00233 if (!param_specs[j]->is_aux() && !param_specs[j]->is_auto()){ 00234 pid_list.push_back(j); 00235 } 00236 } 00237 continue; 00238 } 00239 std::size_t id = find_param_id(param_specs, identifiers[i]); 00240 if (id == PID_BOUND) { 00241 CT_EXCEPTION((std::string("parameter ") + identifiers[i] + " not found").c_str()); 00242 } 00243 if (param_specs[id]->is_auto()) { 00244 CT_EXCEPTION((std::string("parameter ") + identifiers[i] + 00245 " is a auto parameter, and cannot be added to a strength").c_str()); 00246 } 00247 pid_list.push_back(id); 00248 } 00249 // make unique 00250 std::sort(pid_list.begin(), pid_list.end()); 00251 std::vector<std::size_t> unique_pid_list; 00252 for (std::size_t i = 0; i < pid_list.size(); i++) { 00253 if (unique_pid_list.size() == 0 || 00254 pid_list[i] > unique_pid_list.back()) { 00255 unique_pid_list.push_back(pid_list[i]); 00256 } 00257 } 00258 // generate the strengths 00259 if (unique_pid_list.size() < strength) { 00260 CT_EXCEPTION("the parameter list is smaller than the strength"); 00261 } 00262 Strength new_strength; 00263 new_strength.first = unique_pid_list; 00264 new_strength.second = strength; 00265 strengths.push_back(new_strength); 00266 } 00267 00268 PVPair *Assembler::asm_pvpair( 00269 const std::vector<boost::shared_ptr<ParamSpec> > ¶m_specs, 00270 const std::string &identifier, 00271 const TreeNode *value_exp) { 00272 if (value_exp == NULL) { 00273 CT_EXCEPTION("encountered null value expression"); 00274 return 0; 00275 } 00276 if (value_exp->get_str_value() == "") { 00277 CT_EXCEPTION("not a valid value"); 00278 return 0; 00279 } 00280 PVPair *tmp_return = new PVPair(); 00281 std::size_t pid = find_param_id(param_specs, identifier); 00282 if (pid == PID_BOUND) { 00283 // CT_EXCEPTION((std::string("parameter ") + identifier + " not found").c_str()); // no exception now 00284 return 0; 00285 } 00286 if (param_specs[pid]->is_auto()) { 00287 CT_EXCEPTION((std::string("cannot assemble pvpair for auto parameter") + identifier).c_str()); 00288 } 00289 std::size_t vid = param_specs[pid]->query_value_id(value_exp->get_str_value()); 00290 if (vid == VID_BOUND) { 00291 CT_EXCEPTION((std::string("value not found:<")+identifier+","+value_exp->get_str_value()+">").c_str()); 00292 return 0; 00293 } 00294 tmp_return->pid_ = pid; 00295 tmp_return->vid_ = vid; 00296 return tmp_return; 00297 } 00298 00299 TreeNode *Assembler::asm_param(const std::vector<boost::shared_ptr<ParamSpec> > ¶m_specs, const std::string &identifier) { 00300 std::size_t pid = find_param_id(param_specs, identifier); 00301 if (pid == PID_BOUND) { 00302 CT_EXCEPTION((std::string("parameter ") + identifier + " not found").c_str()); 00303 return 0; 00304 } 00305 TreeNode *tmp_return = 0; 00306 if (TYPE_CHECK(param_specs[pid].get(), ParamSpec_String*)) { 00307 Exp_S_Param *exp = new Exp_S_Param(); 00308 exp->set_pid(pid); 00309 tmp_return = exp; 00310 } else if (TYPE_CHECK(param_specs[pid].get(), ParamSpec_Int*)) { 00311 Exp_A_Param *exp = new Exp_A_Param(); 00312 exp->set_pid(pid); 00313 exp->set_type(EAT_INT); 00314 tmp_return = exp; 00315 } else if (TYPE_CHECK(param_specs[pid].get(), ParamSpec_Double*)) { 00316 Exp_A_Param *exp = new Exp_A_Param(); 00317 exp->set_pid(pid); 00318 exp->set_type(EAT_DOUBLE); 00319 tmp_return = exp; 00320 } else if (TYPE_CHECK(param_specs[pid].get(), ParamSpec_Bool*)) { 00321 Constraint_L_Param *constr = new Constraint_L_Param(); 00322 constr->set_pid(pid); 00323 tmp_return = constr; 00324 } else { 00325 CT_EXCEPTION("unrecognized parameter type"); 00326 } 00327 return tmp_return; 00328 } 00329 00330 Constraint_A *Assembler::asm_constraint_a(Exp_A *oprd1, Exp_A *oprd2, eOPERATOR op, double precision) { 00331 if (oprd1 == NULL || oprd2 == NULL) { 00332 CT_EXCEPTION("encountered null oprands"); 00333 return 0; 00334 } 00335 Constraint_A_Binary *tmp_return = 0; 00336 switch (op) { 00337 case OP_EQ: 00338 tmp_return = new Constraint_A_EQ(); 00339 break; 00340 case OP_NE: 00341 tmp_return = new Constraint_A_NE(); 00342 break; 00343 case OP_GT: 00344 tmp_return = new Constraint_A_GT(); 00345 break; 00346 case OP_GE: 00347 tmp_return = new Constraint_A_GE(); 00348 break; 00349 case OP_LT: 00350 tmp_return = new Constraint_A_LT(); 00351 break; 00352 case OP_LE: 00353 tmp_return = new Constraint_A_LE(); 00354 break; 00355 default: 00356 CT_EXCEPTION("unexpected arithmetic constraint type"); 00357 return 0; 00358 break; 00359 } 00360 boost::shared_ptr<Exp_A> tmp_oprd1(oprd1); 00361 boost::shared_ptr<Exp_A> tmp_oprd2(oprd2); 00362 tmp_return->set_loprd(tmp_oprd1); 00363 tmp_return->set_roprd(tmp_oprd2); 00364 tmp_return->set_precision(precision); 00365 return tmp_return; 00366 } 00367 00368 Constraint_S *Assembler::asm_constraint_s(Exp_S *oprd1, Exp_S *oprd2, eOPERATOR op) { 00369 if (oprd1 == NULL || oprd2 == NULL) { 00370 CT_EXCEPTION("encountered null oprands"); 00371 return 0; 00372 } 00373 Constraint_S_Binary *tmp_return = 0; 00374 switch (op) { 00375 case OP_EQ: 00376 tmp_return = new Constraint_S_EQ(); 00377 break; 00378 case OP_NE: 00379 tmp_return = new Constraint_S_NE(); 00380 break; 00381 default: 00382 CT_EXCEPTION("unexpected string constraint type"); 00383 return 0; 00384 break; 00385 } 00386 boost::shared_ptr<Exp_S> tmp_oprd1(oprd1); 00387 boost::shared_ptr<Exp_S> tmp_oprd2(oprd2); 00388 tmp_return->set_loprd(tmp_oprd1); 00389 tmp_return->set_roprd(tmp_oprd2); 00390 return tmp_return; 00391 } 00392 00393 Constraint *Assembler::asm_constraint_asb(TreeNode *oprd1, TreeNode *oprd2, eOPERATOR op, const std::string &str) { 00394 if (oprd1 == NULL || oprd2 == NULL) { 00395 CT_EXCEPTION("encountered null oprands"); 00396 return 0; 00397 } 00398 double precision = this->default_precision_; 00399 bool is_precision_set = false; 00400 std::size_t pos_lbracket = str.find('['); 00401 std::size_t pos_rbracket = str.find(']'); 00402 if (pos_lbracket != std::string::npos && pos_rbracket != std::string::npos && pos_rbracket > pos_lbracket+1) { 00403 is_precision_set = true; 00404 std::string str_precision = str.substr(pos_lbracket+1, pos_rbracket-pos_lbracket-1); 00405 std::stringstream ss(str_precision); 00406 ss >> precision; 00407 precision = fabs(precision); 00408 } 00409 if (TYPE_CHECK(oprd1, Exp_A*) && TYPE_CHECK(oprd2, Exp_A*)) { 00410 Exp_A *exp1 = dynamic_cast<Exp_A *>(oprd1); 00411 Exp_A *exp2 = dynamic_cast<Exp_A *>(oprd2); 00412 return this->asm_constraint_a(exp1, exp2, op, precision); 00413 } 00414 if (TYPE_CHECK(oprd1, Exp_S*) && TYPE_CHECK(oprd2, Exp_S*)) { 00415 if (is_precision_set) { 00416 this->reportWarning("ignoring precision for string relation"); 00417 } 00418 Exp_S *exp1 = dynamic_cast<Exp_S *>(oprd1); 00419 Exp_S *exp2 = dynamic_cast<Exp_S *>(oprd2); 00420 return this->asm_constraint_s(exp1, exp2, op); 00421 } 00422 if (TYPE_CHECK(oprd1, Constraint*) && TYPE_CHECK(oprd2, Constraint*)) { 00423 if (is_precision_set) { 00424 this->reportWarning("ignoring precision for bool relation"); 00425 } 00426 Constraint *constr1 = dynamic_cast<Constraint *>(oprd1); 00427 Constraint *constr2 = dynamic_cast<Constraint *>(oprd2); 00428 return this->asm_constraint_l(constr1, constr2, op); 00429 } 00430 CT_EXCEPTION((std::string("operands mismatch: ")+oprd1->get_class_name()+ " " + oprd2->get_class_name()).c_str()); 00431 return 0; 00432 } 00433 00434 Constraint_L *Assembler::asm_constraint_l(TreeNode *oprd1, TreeNode *oprd2, eOPERATOR op) { 00435 if (oprd1 == NULL || oprd2 == NULL) { 00436 CT_EXCEPTION("encountered null oprands"); 00437 return 0; 00438 } 00439 TYPE_ASSERT(oprd1, Constraint*); 00440 TYPE_ASSERT(oprd2, Constraint*); 00441 Constraint_L_Binary *tmp_return = 0; 00442 switch (op) { 00443 case OP_AND: 00444 tmp_return = new Constraint_L_And(); 00445 break; 00446 case OP_OR: 00447 tmp_return = new Constraint_L_Or(); 00448 break; 00449 case OP_XOR: 00450 case OP_NE: 00451 tmp_return = new Constraint_L_Xor(); 00452 break; 00453 case OP_IMPLY: 00454 tmp_return = new Constraint_L_Imply(); 00455 break; 00456 case OP_IFF: 00457 case OP_EQ: 00458 tmp_return = new Constraint_L_Iff(); 00459 break; 00460 default: 00461 CT_EXCEPTION("unhandled l constraint"); 00462 return 0; 00463 break; 00464 } 00465 Constraint *constr1 = dynamic_cast<Constraint *>(oprd1); 00466 Constraint *constr2 = dynamic_cast<Constraint *>(oprd2); 00467 tmp_return->set_loprd(boost::shared_ptr<Constraint>(constr1)); 00468 tmp_return->set_roprd(boost::shared_ptr<Constraint>(constr2)); 00469 return tmp_return; 00470 } 00471 00472 Constraint_L *Assembler::asm_constraint_l(TreeNode *oprd, eOPERATOR op) { 00473 if (oprd == NULL) { 00474 CT_EXCEPTION("encountered null oprand"); 00475 return 0; 00476 } 00477 TYPE_ASSERT(oprd, Constraint*); 00478 Constraint_L_Unary *tmp_return = 0; 00479 switch (op) { 00480 case OP_NOT: 00481 tmp_return = new Constraint_L_Not(); 00482 break; 00483 default: 00484 CT_EXCEPTION("unhandled l constraint"); 00485 return 0; 00486 break; 00487 } 00488 Constraint *constr = dynamic_cast<Constraint *>(oprd); 00489 tmp_return->set_oprd(boost::shared_ptr<Constraint>(constr)); 00490 return tmp_return; 00491 } 00492 00493 Constraint_L_CBool *Assembler::asm_constraint_l_cbool(const std::string &val) { 00494 Constraint_L_CBool *constr = new Constraint_L_CBool(); 00495 if (val == "true") { 00496 constr->set_value(true); 00497 } else if (val == "false") { 00498 constr->set_value(false); 00499 } else { 00500 CT_EXCEPTION("unrecognized boolean value"); 00501 } 00502 return constr; 00503 } 00504 00505 Exp_A *Assembler::asm_exp_a(TreeNode *oprd1, TreeNode *oprd2, eOPERATOR op) { 00506 if (oprd1 == NULL || oprd2 == NULL) { 00507 CT_EXCEPTION("encountered null oprands"); 00508 return 0; 00509 } 00510 TYPE_ASSERT(oprd1, Exp_A*); 00511 TYPE_ASSERT(oprd2, Exp_A*); 00512 Exp_A *c_oprd1 = dynamic_cast<Exp_A *>(oprd1); 00513 Exp_A *c_oprd2 = dynamic_cast<Exp_A *>(oprd2); 00514 Exp_A_Binary *tmp_return = 0; 00515 switch (op) { 00516 case OP_ADD: 00517 tmp_return = new Exp_A_Add(); 00518 break; 00519 case OP_DIV: 00520 tmp_return = new Exp_A_Div(); 00521 break; 00522 case OP_MOD: 00523 if (c_oprd1->get_type() != EAT_INT || 00524 c_oprd2->get_type() != EAT_INT) { 00525 CT_EXCEPTION("the operands of \'%\' must be integers"); 00526 } 00527 tmp_return = new Exp_A_Mod(); 00528 break; 00529 case OP_MULT: 00530 tmp_return = new Exp_A_Mult(); 00531 break; 00532 case OP_SUB: 00533 tmp_return = new Exp_A_Sub(); 00534 break; 00535 default: 00536 CT_EXCEPTION("unhandled exp type"); 00537 return 0; 00538 break; 00539 } 00540 tmp_return->set_loprd(boost::shared_ptr<TreeNode>(c_oprd1)); 00541 tmp_return->set_roprd(boost::shared_ptr<TreeNode>(c_oprd2)); 00542 if (c_oprd1->get_type() == EAT_INT && 00543 c_oprd2->get_type() == EAT_INT) { 00544 tmp_return->set_type(EAT_INT); 00545 } else if (c_oprd1->get_type() == EAT_DOUBLE || 00546 c_oprd2->get_type() == EAT_DOUBLE) { 00547 tmp_return->set_type(EAT_DOUBLE); 00548 } else { 00549 CT_EXCEPTION("cannot determine the parent expression type"); 00550 } 00551 return tmp_return; 00552 } 00553 00554 Exp_A *Assembler::asm_exp_a(TreeNode *oprd, eOPERATOR op) { 00555 if (oprd == NULL) { 00556 CT_EXCEPTION("encountered null oprand"); 00557 return 0; 00558 } 00559 TYPE_ASSERT(oprd, Exp_A*); 00560 Exp_A *c_oprd = dynamic_cast<Exp_A*>(oprd); 00561 switch (op) { 00562 case OP_NEG: { 00563 Exp_A_Unary *tmp_return = 0; 00564 tmp_return = new Exp_A_Neg(); 00565 tmp_return->set_oprd(boost::shared_ptr<TreeNode>(c_oprd)); 00566 tmp_return->set_type(c_oprd->get_type()); 00567 return tmp_return; 00568 break; 00569 } 00570 case OP_UPLUS: 00571 return c_oprd; 00572 break; 00573 default: 00574 CT_EXCEPTION("unhandled exp type"); 00575 return 0; 00576 break; 00577 } 00578 } 00579 00580 Exp_A *Assembler::asm_exp_a_cast(TreeNode *oprd, const std::string &type) { 00581 if (oprd == NULL) { 00582 CT_EXCEPTION("encountered null oprand"); 00583 return 0; 00584 } 00585 if (TYPE_CHECK(oprd, Exp_A*)) { 00586 Exp_A *exp = dynamic_cast<Exp_A *>(oprd); 00587 Exp_A_Cast *tmp_return = new Exp_A_Cast(); 00588 if (type == "int") { 00589 tmp_return->set_type(EAT_INT); 00590 } else if (type == "double") { 00591 tmp_return->set_type(EAT_DOUBLE); 00592 } else { 00593 CT_EXCEPTION((std::string("cannot cast to type ") + type).c_str()); 00594 return 0; 00595 } 00596 tmp_return->set_oprd(boost::shared_ptr<TreeNode>(exp)); 00597 return tmp_return; 00598 } else if (TYPE_CHECK(oprd, Constraint*)) { 00599 Constraint *constr = dynamic_cast<Constraint *>(oprd); 00600 Exp_A_ConstraintCast *tmp_return = new Exp_A_ConstraintCast(); 00601 if (type == "int") { 00602 tmp_return->set_type(EAT_INT); 00603 } else if (type == "double") { 00604 tmp_return->set_type(EAT_DOUBLE); 00605 } else { 00606 CT_EXCEPTION((std::string("cannot cast to type ") + type).c_str()); 00607 return 0; 00608 } 00609 tmp_return->set_oprd(boost::shared_ptr<TreeNode>(constr)); 00610 return tmp_return; 00611 } 00612 CT_EXCEPTION((std::string("cannot cast from ") + oprd->get_class_name()).c_str()); 00613 return 0; 00614 } 00615 00616 Constraint *Assembler::asm_constraint_invalid( 00617 const std::vector<boost::shared_ptr<ParamSpec> > ¶m_specs, 00618 const std::string &identifier) { 00619 std::size_t pid = find_param_id(param_specs, identifier); 00620 if (pid == PID_BOUND) { 00621 this->reportWarning(std::string("cannot find parameter ") + identifier + " when assembling parameter invalidation constraints, neglecting"); 00622 return 0; 00623 } 00624 // FIXME: the semantics for invalidating auto parameters are not defined 00625 //if (param_specs[pid]->is_auto()) { 00626 // this->reportWarning(std::string("parameter ") + identifier + " cannot be invalidated since it is aux or auto"); 00627 // return 0; 00628 //} 00629 Constraint_L_IVLD *constr = new Constraint_L_IVLD(); 00630 constr->set_pid(pid); 00631 return constr; 00632 } 00633 00634 void Assembler::store_invalidation( 00635 const std::vector<boost::shared_ptr<ParamSpec> > ¶m_specs, 00636 const std::vector<std::string> &identifiers, 00637 const boost::shared_ptr<TreeNode> &precond) { 00638 for (std::size_t i = 0; i < identifiers.size(); ++i) { 00639 std::size_t pid = find_param_id(param_specs, identifiers[i]); 00640 if (pid == PID_BOUND) { 00641 this->reportWarning(std::string("cannot find parameter ") + identifiers[i] + " when assembling parameter invalidation constraints, neglecting"); 00642 continue; 00643 } 00644 this->stored_invalidations_[pid].push_back(precond); 00645 } 00646 } 00647 00648 std::vector<boost::shared_ptr<Constraint> > Assembler::dump_invalidations(const std::vector<boost::shared_ptr<ParamSpec> > ¶m_specs) { 00649 std::vector<boost::shared_ptr<Constraint> > tmp_return; 00650 for (std::size_t i = 0; i < param_specs.size(); ++i) { 00651 std::size_t pid = i; 00652 // FIXME: the semantics for invalidating auto parameters are not defined 00653 //if (param_specs[pid]->is_auto()) { 00654 // // cannot proceed with auto parameters 00655 // continue; 00656 //} 00657 const std::vector<boost::shared_ptr<TreeNode> > &constrs = this->stored_invalidations_[pid]; 00658 boost::shared_ptr<Constraint_L_IVLD> constr_ivld(new Constraint_L_IVLD()); 00659 constr_ivld->set_pid(pid); 00660 { 00661 if (constrs.size() == 0) { 00662 boost::shared_ptr<Constraint_L_Not> constr_nivld(new Constraint_L_Not()); 00663 constr_nivld->set_oprd(constr_ivld); 00664 tmp_return.push_back(constr_nivld); 00665 } else { 00666 boost::shared_ptr<Constraint> constr_conjunction; 00667 for (std::size_t i = 0; i < constrs.size(); ++i) { 00668 boost::shared_ptr<Constraint> this_constr = boost::dynamic_pointer_cast<Constraint>(constrs[i]); 00669 if (!constrs[i]) { 00670 std::stringstream ss; 00671 ss << "condition #" << i+1 << " for invalidating parameter " << param_specs[pid]->get_param_name() << " is not a condition"; 00672 this->reportError(ss.str()); 00673 return tmp_return; 00674 } 00675 if (i == 0) { 00676 constr_conjunction = this_constr; 00677 } else { 00678 boost::shared_ptr<Constraint_L_Or> constr_or(new Constraint_L_Or()); 00679 constr_or->set_loprd(constr_conjunction); 00680 constr_or->set_roprd(this_constr); 00681 constr_conjunction = constr_or; 00682 } 00683 } 00684 boost::shared_ptr<Constraint_L_Iff> constr_to_add(new Constraint_L_Iff()); 00685 constr_to_add->set_loprd(constr_conjunction); 00686 constr_to_add->set_roprd(constr_ivld); 00687 tmp_return.push_back(constr_to_add); 00688 } 00689 } 00690 } 00691 return tmp_return; 00692 } 00693 00694 Seed *Assembler::asm_seed(std::size_t id, const ct::common::Tuple &tuple) { 00695 Seed_Tuple *seed = new Seed_Tuple(); 00696 seed->set_id(id); 00697 seed->the_tuple() = tuple; 00698 return seed; 00699 } 00700 00701 Seed *Assembler::asm_seed(std::size_t id, Constraint *constr) { 00702 Seed_Constraint *seed = new Seed_Constraint(); 00703 seed->set_id(id); 00704 seed->the_constraint().reset(constr); 00705 return seed; 00706 } 00707 00708 void Assembler::set_option(const std::string &identifier, const ct::common::TreeNode *value) { 00709 if (identifier == "default_precision") { 00710 if (dynamic_cast<const Exp_A_CInt*>(value)) { 00711 this->default_precision_ = dynamic_cast<const Exp_A_CInt*>(value)->get_value(); 00712 } else if (dynamic_cast<const Exp_A_CDouble*>(value)) { 00713 this->default_precision_ = dynamic_cast<const Exp_A_CDouble*>(value)->get_value(); 00714 } else { 00715 CT_EXCEPTION(std::string("invalid value for option ")+identifier); 00716 } 00717 } else { 00718 CT_EXCEPTION("unhandled option"); 00719 } 00720 }