// Copyright (C) 2006, Ondra Kamenik // $Id: atom_assignings.cpp 92 2007-04-19 11:38:21Z ondra $ #include "atom_assignings.h" #include "location.h" #include "parser_exception.h" #include "utils/cc/exception.h" #include #include using namespace ogp; AtomAssignings::AtomAssignings(const AtomAssignings& aa, ogp::StaticAtoms& a) : atoms(a), expr(aa.expr, atoms), left_names(aa.left_names), order(aa.order) { // fill the lname2expr for (Tvarintmap::const_iterator it = aa.lname2expr.begin(); it != aa.lname2expr.end(); ++it) lname2expr.insert(Tvarintmap::value_type(left_names.query((*it).first), (*it).second)); } /** A global symbol for passing info to the AtomAssignings from * asgn_parse(). */ AtomAssignings* aparser; /** The declaration of functions defined in asgn_ll.cc and asgn_tab.cc * generated from assign.lex assign.y */ void* asgn__scan_buffer(char*, size_t); void asgn__destroy_buffer(void*); void asgn_parse(); extern location_type asgn_lloc; void AtomAssignings::parse(int length, const char* stream) { char* buffer = new char[length+2]; strncpy(buffer, stream, length); buffer[length] = '\0'; buffer[length+1] = '\0'; asgn_lloc.off = 0; asgn_lloc.ll = 0; void* p = asgn__scan_buffer(buffer, (unsigned int)length+2); aparser = this; asgn_parse(); delete [] buffer; asgn__destroy_buffer(p); } void AtomAssignings::error(const char* mes) { throw ParserException(mes, asgn_lloc.off); } void AtomAssignings::add_assignment_to_double(const char* name, double val) { // if left hand side is a registered atom, insert it to tree int t; try { if (atoms.check(name)) t = expr.add_nulary(name); else t = -1; } catch (const ParserException& e) { t = -1; } // register left hand side in order order.push_back(t); // add the double to the tree char tmp[100]; sprintf(tmp, "%30.25g", val); try { expr.parse(strlen(tmp), tmp); } catch (const ParserException& e) { // should never happen throw ParserException(string("Error parsing double ")+tmp+": "+e.message(), 0); } // register name of the left hand side and put to lname2expr const char* ss = left_names.insert(name); lname2expr.insert(Tvarintmap::value_type(ss, order.size()-1)); } void AtomAssignings::add_assignment(int asgn_off, const char* str, int name_len, int right_off, int right_len) { // the order of doing things here is important: since the // FormulaParser requires that all references from the i-th tree // refere to trees with index lass than i, so to capture also a // nulary term for the left hand side, it must be inserted to the // expression tree before the expression is parsed. // find the name in the atoms, make copy of name to be able to put // '\0' at the end char* buf = new char[name_len+1]; strncpy(buf, str, name_len); buf[name_len] = '\0'; // if left hand side is a registered atom, insert it to tree int t; try { t = atoms.check(buf); if (t == -1) t = expr.add_nulary(buf); } catch (const ParserException& e) { atoms.register_name(buf); t = expr.add_nulary(buf); } // register left hand side in order order.push_back(t); // parse expression on the right try { expr.parse(right_len, str+right_off); } catch (const ParserException& e) { throw ParserException(e, asgn_off+right_off); } // register name of the left hand side and put to lname2expr const char* ss = left_names.insert(buf); if (lname2expr.find(ss) != lname2expr.end()) { // Prevent the occurrence of #415 std::cerr << "Changing the value of " << ss << " is not supported. Aborting." << std::endl; exit(EXIT_FAILURE); } lname2expr[ss] = order.size()-1; // delete name delete [] buf; } void AtomAssignings::apply_subst(const AtomSubstitutions::Toldnamemap& mm) { // go through all old variables and see what are their derived new // variables for (AtomSubstitutions::Toldnamemap::const_iterator it = mm.begin(); it != mm.end(); ++it) { const char* oldname = (*it).first; const AtomSubstitutions::Tshiftnameset& sset = (*it).second; if (! sset.empty()) { int told = atoms.index(oldname); if (told < 0 && ! atoms.get_name_storage().query(oldname)) atoms.register_name(oldname); if (told == -1) told = expr.add_nulary(oldname); // at least one substitution here, so make an expression expr.add_formula(told); // say that this expression is not assigned to any atom order.push_back(-1); // now go through all new names derived from the old name and // reference to the newly added formula for (AtomSubstitutions::Tshiftnameset::const_iterator itt = sset.begin(); itt != sset.end(); ++itt) { const char* newname = (*itt).first; const char* nn = left_names.insert(newname); lname2expr.insert(Tvarintmap::value_type(nn, expr.nformulas()-1)); } } } } void AtomAssignings::print() const { printf("Atom Assignings\nExpressions:\n"); expr.print(); printf("Left names:\n"); for (Tvarintmap::const_iterator it = lname2expr.begin(); it != lname2expr.end(); ++it) printf("%s ==> %d (t=%d)\n", (*it).first, expr.formula((*it).second), order[(*it).second]); } void AtomAsgnEvaluator::setValues(EvalTree& et) const { // set values of constants aa.atoms.setValues(et); // set values of variables to NaN or to user set values double nan = std::numeric_limits::quiet_NaN(); for (int i = 0; i < aa.atoms.nvar(); i++) { const char* ss = aa.atoms.name(i); int t = aa.atoms.index(ss); if (t >= 0) { Tusrvalmap::const_iterator it = user_values.find(t); if (it == user_values.end()) et.set_nulary(t, nan); else et.set_nulary(t, (*it).second); } } } void AtomAsgnEvaluator::set_user_value(const char* name, double val) { int t = aa.atoms.index(name); if (t >= 0) { Tusrvalmap::iterator it = user_values.find(t); if (it == user_values.end()) user_values.insert(Tusrvalmap::value_type(t, val)); else (*it).second = val; } } void AtomAsgnEvaluator::load(int i, double res) { // set the value operator[](i) = res; // if i-th expression is atom, set its value to this EvalTree int t = aa.order[i]; if (t >= 0) etree.set_nulary(t, res); } double AtomAsgnEvaluator::get_value(const char* name) const { AtomAssignings::Tvarintmap::const_iterator it = aa.lname2expr.find(name); if (it == aa.lname2expr.end()) return std::numeric_limits::quiet_NaN(); else return operator[]((*it).second); }