OTScript::~OTScript()
{
    // mapOfParties; // NO NEED to clean this up, since OTScript doesn't own the parties.
    // See OTSmartContract, rather, for that.
    
    while (!m_mapVariables.empty())
    {
        OTVariable * pVar = m_mapVariables.begin()->second;
        OT_ASSERT(NULL != pVar);

        // NOTE: We're NOT going to delete pVar, since we don't own it.
        // But we ARE going to remove pVar's pointer to this script, so
        // pVar doesn't dereference a bad pointer later on.
        //
        pVar->UnregisterScript();
        m_mapVariables.erase(m_mapVariables.begin());
    }
}
// If a variable is set onto a script, it sets an internal pointer to that script.
// Later, when the variable destructs, if that pointer is set, it removes itself
// from the script by calling this function. (Yes, this would be better with smart
// pointers. C++11 here we come!)
//
void OTScript::RemoveVariable (OTVariable & theVar)
{
    const std::string str_var_name  = theVar.GetName().Get();
    mapOfVariables::iterator it_var = m_mapVariables.find(str_var_name);
    
    if (it_var != m_mapVariables.end())
    {
        m_mapVariables.erase(it_var); // no need to delete the variable pointer since the script doesn't own it anyway. 
    }
}
Esempio n. 3
0
void OTBylaw::Serialize(OTString & strAppend,
						bool bCalculatingID/*=false*/)
{
	strAppend.Concatenate("<bylaw\n name=\"%s\"\n"
						  " numVariables=\"%d\"\n"
						  " numClauses=\"%d\"\n"
						  " numHooks=\"%d\"\n"
						  " numCallbacks=\"%d\"\n"
						  " language=\"%s\" >\n\n",
						  m_strName.Get(),
						  m_mapVariables.size(), // HOW MANY VARIABLES?
						  m_mapClauses.size(), // HOW MANY CLAUSES?
						  m_mapHooks.size(), // How many HOOKS?
						  m_mapCallbacks.size(), // How many CALLBACK?
						  m_strLanguage.Get());
	// ------------------------------

	FOR_EACH(mapOfVariables, m_mapVariables)
	{
		OTVariable * pVar = (*it).second;
		OT_ASSERT(NULL != pVar);

		pVar->Serialize(strAppend, bCalculatingID); // Variables save in a specific state during ID calculation (no matter their current actual value.)
	}
Esempio n. 4
0
// 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;
}
Esempio n. 5
0
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;
}