// Done bool OTVariable::Compare(OTVariable & rhs) { if (!(GetName().Compare(rhs.GetName()))) { OTLog::vOutput(0, "OTVariable::Compare: Names don't match: %s / %s \n", GetName().Get(), rhs.GetName().Get()); return false; } if ( ! (GetType() == rhs.GetType()) ) { OTLog::vOutput(0, "OTVariable::Compare: Type doesn't match: %s \n", GetName().Get()); return false; } if ( ! (GetAccess() == rhs.GetAccess()) ) { OTLog::vOutput(0, "OTVariable::Compare: Access types don't match: %s \n", GetName().Get()); return false; } // ------------------------------- bool bMatch = false; switch (GetType()) { case OTVariable::Var_Integer: bMatch = (GetValueInteger() == rhs.GetValueInteger()); break; case OTVariable::Var_Bool: bMatch = (GetValueBool() == rhs.GetValueBool()); break; case OTVariable::Var_String: bMatch = (GetValueString().compare(rhs.GetValueString()) == 0); break; default: OTLog::vError("OTVariable::Compare: Unknown type in variable %s.\n", m_strName.Get()); break; } return bMatch; }
bool OTScriptChai::ExecuteScript(OTVariable* pReturnVar) { using namespace chaiscript; OT_ASSERT(nullptr != chai); if (m_str_script.size() > 0) { /* chai->add(user_type<OTParty>(), "OTParty"); chai->add(constructor<OTParty()>(), "OTParty"); chai->add(constructor<OTParty(const OTParty&)>(), "OTParty"); chai->add(fun<OTParty&(OTParty::*)(const OTParty&)>(&OTParty::operator=), "="); chai->add(fun(&OTParty::GetPartyName), "GetPartyName"); chai->add(fun(&OTParty::GetNymID), "GetNymID"); chai->add(fun(&OTParty::GetEntityID), "GetEntityID"); chai->add(fun(&OTParty::GetPartyID), "GetPartyID"); chai->add(fun(&OTParty::HasActiveAgent), "HasActiveAgent"); */ // etc // chai->add(m); // Here we add the OTParty class to the // chaiscript engine. for (auto& it : m_mapParties) { OTParty* pParty = it.second; OT_ASSERT(nullptr != pParty); std::string party_name = pParty->GetPartyName(); // std::cerr << " TESTING PARTY: " << party_name << // std::endl; // chai->add(chaiscript::var(&d), "d"); // Currently I don't make the entire party available -- just his ID. // // Update: The client side uses constant variables only (a block or // two down // from here) and it stores the user's ID, and acct IDs, directly in // those // variables based on name. Whereas the server side passes in // Parties and // PartyAccounts, and only the names are made available inside the // scripts. // This way the scripts must entirely rely on the server-side API, // functions // such as move_funds(from_name, to_name), which expect a name, and // translate // only internally to resolve the ID. // (Contrast this with client-side scripts, which actually have the // real ID // available inside the script, and which can call any OT API // function that // exists...) // chai->add_global_const(const_var(party_name), party_name.c_str()); // Why name and not // ID? See comment // just above. } for (auto& it : m_mapAccounts) { OTPartyAccount* pAcct = it.second; OT_ASSERT(nullptr != pAcct); std::string acct_name = pAcct->GetName().Get(); // std::cerr << " TESTING ACCOUNT: " << acct_name << // std::endl; // chai->add(chaiscript::var(&d), "d"); // Currently I don't make the entire account available -- just his // ID. // chai->add_global_const(const_var(acct_name), acct_name.c_str()); // See comment in // above block for // party name. } /* enum OTVariable_Access { Var_Constant, // Constant -- you cannot change this value. Var_Persistent, // Persistent -- changing value doesn't require notice to parties. Var_Important, // Important -- changing value requires notice to parties. Var_Error_Access // should never happen. }; OTVariable_Access GetAccess() const { return m_Access; } int64_t& GetValueLong() { return m_lValue; } bool& GetValueBool() { return m_bValue; } std::string& GetValueString() { return m_str_Value; } */ for (auto& it : m_mapVariables) { const std::string var_name = it.first; OTVariable* pVar = it.second; OT_ASSERT((nullptr != pVar) && (var_name.size() > 0)); switch (pVar->GetType()) { case OTVariable::Var_Integer: { int32_t& nValue = pVar->GetValueInteger(); if (OTVariable::Var_Constant == pVar->GetAccess()) // no pointer here, since it's constant. chai->add_global_const(const_var(pVar->CopyValueInteger()), var_name.c_str()); else chai->add(var(&nValue), // passing ptr here so the // script can modify this // variable if it wants. var_name.c_str()); } break; case OTVariable::Var_Bool: { bool& bValue = pVar->GetValueBool(); if (OTVariable::Var_Constant == pVar->GetAccess()) // no pointer here, since it's constant. chai->add_global_const(const_var(pVar->CopyValueBool()), var_name.c_str()); else chai->add(var(&bValue), // passing ptr here so the // script can modify this // variable if it wants. var_name.c_str()); } break; case OTVariable::Var_String: { std::string& str_Value = pVar->GetValueString(); if (OTVariable::Var_Constant == pVar->GetAccess()) // no pointer here, since it's constant. { chai->add_global_const(const_var(pVar->CopyValueString()), var_name.c_str()); // otErr << "\n\n\nOTSCRIPT DEBUGGING // (const var added to script): %s\n\n\n", // str_Value.c_str()); } else { chai->add(var(&str_Value), // passing ptr here so the // script can modify this // variable if it wants. var_name.c_str()); // otErr << "\n\n\nOTSCRIPT DEBUGGING // var added to script: %s \n\n\n", str_Value.c_str()); } } break; default: otErr << "OTScriptChai::ExecuteScript: Failure: Unknown " "variable type for variable: " << var_name << "\n"; return false; } } // Here we add the mapOfParties user-defined type to the chaiscript // engine. // chai->add(user_type<mapOfParties>(), "mapOfParties"); // Here we add the m_mapParties member variable itself // chai->add_global_const(const_var(m_mapParties), // "Parties"); try { if (nullptr == pReturnVar) // Nothing to return. chai->eval(m_str_script.c_str(), exception_specification<const std::exception&>(), m_str_display_filename); else // There's a return variable. { switch (pReturnVar->GetType()) { case OTVariable::Var_Integer: { int32_t nResult = chai->eval<int32_t>( m_str_script.c_str(), exception_specification<const std::exception&>(), m_str_display_filename); pReturnVar->SetValue(nResult); } break; case OTVariable::Var_Bool: { bool bResult = chai->eval<bool>( m_str_script.c_str(), exception_specification<const std::exception&>(), m_str_display_filename); pReturnVar->SetValue(bResult); } break; case OTVariable::Var_String: { std::string str_Result = chai->eval<std::string>( m_str_script.c_str(), exception_specification<const std::exception&>(), m_str_display_filename); pReturnVar->SetValue(str_Result); } break; default: otErr << "OTScriptChai::ExecuteScript: Unknown return type " "passed in, " "unable to service it.\n"; return false; } // switch } // else return variable. } // try catch (const chaiscript::exception::eval_error& ee) { // Error in script parsing / execution otErr << "OTScriptChai::ExecuteScript: \n Caught " "chaiscript::exception::eval_error: \n " << ee.reason << ". \n File: " << ee.filename << "\n" " Start position, line: " << ee.start_position.line << " column: " << ee.start_position.column << "\n" " End position, line: " << ee.end_position.line << " column: " << ee.end_position.column << "\n\n"; std::cout << ee.what(); if (ee.call_stack.size() > 0) { std::cout << "during evaluation at (" << ee.call_stack[0]->start.line << ", " << ee.call_stack[0]->start.column << ")"; } std::cout << std::endl; std::cout << std::endl; // std::cout << ee.what(); if (ee.call_stack.size() > 0) { // std::cout << "during evaluation at (" << // *(ee.call_stack[0]->filename) << " " << // ee.call_stack[0]->start.line << ", " << // ee.call_stack[0]->start.column << ")"; // const std::string text; // boost::shared_ptr<const std::string> filename; for (size_t j = 1; j < ee.call_stack.size(); ++j) { if (ee.call_stack[j]->identifier != chaiscript::AST_Node_Type::Block && ee.call_stack[j]->identifier != chaiscript::AST_Node_Type::File) { std::cout << std::endl; std::cout << " from " << *(ee.call_stack[j]->filename) << " (" << ee.call_stack[j]->start.line << ", " << ee.call_stack[j]->start.column << ") : "; std::cout << ee.call_stack[j]->text << std::endl; } } } std::cout << std::endl; return false; } catch (const chaiscript::exception::bad_boxed_cast& e) { // Error unboxing return value otErr << "OTScriptChai::ExecuteScript: Caught " "chaiscript::exception::bad_boxed_cast : " << ((e.what() != nullptr) ? e.what() : "e.what() returned null, sorry") << ".\n"; return false; } catch (const std::exception& e) { // Error explicitly thrown from script otErr << "OTScriptChai::ExecuteScript: Caught std::exception " "exception: " << ((e.what() != nullptr) ? e.what() : "e.what() returned null, sorry") << "\n"; return false; } // catch (chaiscript::Boxed_Value bv) catch (...) { // int32_t i = chaiscript::boxed_cast<int32_t>(bv); otErr << "OTScriptChai::ExecuteScript: Caught exception.\n"; return false; } } return true; }