ct_common  1.0.1
Common library for combinatorial testing
src/ct_common/file_parse/assembler.cpp
Go to the documentation of this file.
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> > &param_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> > &param_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> > &param_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> > &param_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> > &param_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> > &param_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> > &param_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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines