Improve performance for loop and insertion
[scilab.git] / scilab / modules / ast / src / cpp / types / macro.cpp
index c7357ed..3dfaba0 100644 (file)
@@ -29,14 +29,14 @@ extern "C"
 #include "Scierror.h"
 #include "sciprint.h"
 #include "sci_malloc.h"
-#include "os_swprintf.h"
+#include "os_string.h"
 }
 
 namespace types
 {
 Macro::Macro(const std::wstring& _stName, std::list<symbol::Variable*>& _inputArgs, std::list<symbol::Variable*>& _outputArgs, ast::SeqExp &_body, const std::wstring& _stModule):
     Callable(),
-    m_inputArgs(&_inputArgs), m_outputArgs(&_outputArgs), m_body(&_body),
+    m_inputArgs(&_inputArgs), m_outputArgs(&_outputArgs), m_body(_body.clone()),
     m_Nargin(symbol::Context::getInstance()->getOrCreate(symbol::Symbol(L"nargin"))),
     m_Nargout(symbol::Context::getInstance()->getOrCreate(symbol::Symbol(L"nargout"))),
     m_Varargin(symbol::Context::getInstance()->getOrCreate(symbol::Symbol(L"varargin"))),
@@ -50,11 +50,12 @@ Macro::Macro(const std::wstring& _stName, std::list<symbol::Variable*>& _inputAr
     m_pDblArgOut = new Double(1);
     m_pDblArgOut->IncreaseRef(); //never delete
 
+    m_body->setReturnable();
 }
 
 Macro::~Macro()
 {
-    //delete m_body;
+    delete m_body;
     m_pDblArgIn->DecreaseRef();
     m_pDblArgIn->killMe();
     m_pDblArgOut->DecreaseRef();
@@ -69,6 +70,14 @@ Macro::~Macro()
     {
         delete m_outputArgs;
     }
+
+    for (const auto & sub : m_submacro)
+    {
+        sub.second->DecreaseRef();
+        sub.second->killMe();
+    }
+
+    m_submacro.clear();
 }
 
 void Macro::cleanCall(symbol::Context * pContext, int oldPromptMode)
@@ -98,7 +107,54 @@ ast::SeqExp* Macro::getBody(void)
 
 bool Macro::toString(std::wostringstream& ostr)
 {
-    ostr << L"FIXME : Implement Macro::toString" << std::endl;
+    // get macro name
+    wchar_t* wcsVarName = os_wcsdup(ostr.str().c_str());
+    ostr.str(L"");
+
+    ostr << L"[";
+
+    // output arguments [a,b,c] = ....
+    if (m_outputArgs->empty() == false)
+    {
+        std::list<symbol::Variable*>::iterator OutArg = m_outputArgs->begin();
+        std::list<symbol::Variable*>::iterator OutArgfter = OutArg;
+        OutArgfter++;
+
+        for (; OutArgfter != m_outputArgs->end(); OutArgfter++)
+        {
+            ostr << (*OutArg)->getSymbol().getName();
+            ostr << ",";
+            OutArg++;
+        }
+
+        ostr << (*OutArg)->getSymbol().getName();
+    }
+
+    ostr << L"]";
+
+    // function name
+    ostr << L"=" << wcsVarName << L"(";
+
+    // input arguments function(a,b,c)
+    if (m_inputArgs->empty() == false)
+    {
+        std::list<symbol::Variable*>::iterator inArg = m_inputArgs->begin();
+        std::list<symbol::Variable*>::iterator inRagAfter = inArg;
+        inRagAfter++;
+
+        for (; inRagAfter != m_inputArgs->end(); inRagAfter++)
+        {
+            ostr << (*inArg)->getSymbol().getName();
+            ostr << ",";
+            inArg++;
+        }
+
+        ostr << (*inArg)->getSymbol().getName();
+    }
+
+    ostr << L")" << std::endl;
+
+    FREE(wcsVarName);
     return true;
 }
 
@@ -118,7 +174,7 @@ Callable::ReturnValue Macro::call(typed_list &in, optional_list &opt, int _iRetC
     // but not more execpts with varargin
 
     // varargin management
-    if (m_inputArgs->size() > 0 && m_inputArgs->back()->name_get().name_get() == L"varargin")
+    if (m_inputArgs->size() > 0 && m_inputArgs->back()->getSymbol().getName() == L"varargin")
     {
         int iVarPos = static_cast<int>(in.size());
         if (iVarPos > static_cast<int>(m_inputArgs->size()) - 1)
@@ -177,18 +233,11 @@ Callable::ReturnValue Macro::call(typed_list &in, optional_list &opt, int _iRetC
     }
     else
     {
-        //add optional paramter in current scope
-        optional_list::const_iterator it;
-        for (it = opt.begin() ; it != opt.end() ; it++)
-        {
-            pContext->put(symbol::Symbol(it->first), it->second);
-        }
-
         //assign value to variable in the new context
         std::list<symbol::Variable*>::iterator i;
         typed_list::const_iterator j;
 
-        for (i = m_inputArgs->begin(), j = in.begin(); j != in.end (); ++j, ++i)
+        for (i = m_inputArgs->begin(), j = in.begin(); j != in.end(); ++j, ++i)
         {
             if (*j)
             {
@@ -196,6 +245,15 @@ Callable::ReturnValue Macro::call(typed_list &in, optional_list &opt, int _iRetC
                 pContext->put(*i, *j);
             }
         }
+
+        //add optional paramter in current scope
+        optional_list::const_iterator it;
+        for (it = opt.begin() ; it != opt.end() ; it++)
+        {
+            pContext->put(symbol::Symbol(it->first), it->second);
+        }
+
+
     }
 
     // varargout management
@@ -204,7 +262,7 @@ Callable::ReturnValue Macro::call(typed_list &in, optional_list &opt, int _iRetC
     // varargout is a list
     // varargout can containt more items than caller need
     // varargout must containt at leat caller needs
-    if (m_outputArgs->size() == 1 && m_outputArgs->back()->name_get().name_get() == L"varargout")
+    if (m_outputArgs->size() == 1 && m_outputArgs->back()->getSymbol().getName() == L"varargout")
     {
         bVarargout = true;
         List* pL = new List();
@@ -233,6 +291,13 @@ Callable::ReturnValue Macro::call(typed_list &in, optional_list &opt, int _iRetC
     pContext->put(m_Nargin, m_pDblArgIn);
     pContext->put(m_Nargout, m_pDblArgOut);
 
+
+    //add sub macro in current context
+    for (const auto & sub : m_submacro)
+    {
+        pContext->put(sub.first, sub.second);
+    }
+
     //save current prompt mode
     int oldVal = ConfigVariable::getPromptMode();
     try
@@ -242,14 +307,9 @@ Callable::ReturnValue Macro::call(typed_list &in, optional_list &opt, int _iRetC
         //m_body->accept(mute);
 
         ConfigVariable::setPromptMode(-1);
-        m_body->returnable_set();
         m_body->accept(*execFunc);
         //restore previous prompt mode
         ConfigVariable::setPromptMode(oldVal);
-        if (m_body->is_return())
-        {
-            m_body->returnable_set();
-        }
     }
     catch (ast::ScilabMessage & sm)
     {
@@ -282,7 +342,7 @@ Callable::ReturnValue Macro::call(typed_list &in, optional_list &opt, int _iRetC
         }
 
         List* pVarOut = pOut->getAs<List>();
-        const int size = std::max(pVarOut->getSize(), _iRetCount);
+        const int size = std::min(pVarOut->getSize(), _iRetCount);
         for (int i = 0 ; i < size ; ++i)
         {
             InternalType* pIT = pVarOut->get(i);
@@ -300,7 +360,8 @@ Callable::ReturnValue Macro::call(typed_list &in, optional_list &opt, int _iRetC
                 return Callable::Error;
             }
 
-            out.push_back(pIT->clone());
+            pIT->IncreaseRef();
+            out.push_back(pIT);
         }
     }
     else
@@ -325,7 +386,7 @@ Callable::ReturnValue Macro::call(typed_list &in, optional_list &opt, int _iRetC
                 out.clear();
                 cleanCall(pContext, oldVal);
 
-                char* pst = wide_string_to_UTF8((*i)->name_get().name_get().c_str());
+                char* pst = wide_string_to_UTF8((*i)->getSymbol().getName().c_str());
                 Scierror(999, _("Undefined variable %s.\n"), pst);
                 FREE(pst);
                 return Callable::Error;
@@ -361,7 +422,7 @@ int Macro::getNbInputArgument(void)
 
 int Macro::getNbOutputArgument(void)
 {
-    if (m_outputArgs->size() == 1 && m_outputArgs->back()->name_get().name_get() == L"varargout")
+    if (m_outputArgs->size() == 1 && m_outputArgs->back()->getSymbol().getName() == L"varargout")
     {
         return -1;
     }
@@ -393,7 +454,7 @@ bool Macro::operator==(const InternalType& it)
 
     for (; itOld != itEndOld ; ++itOld, ++itMacro)
     {
-        if ((*itOld)->name_get() != (*itMacro)->name_get())
+        if ((*itOld)->getSymbol() != (*itMacro)->getSymbol())
         {
             return false;
         }
@@ -401,13 +462,18 @@ bool Macro::operator==(const InternalType& it)
 
     //check outputs
     pOutput = pRight->outputs_get();
+    if (pOutput->size() != m_outputArgs->size())
+    {
+        return false;
+    }
+
     itOld = pOutput->begin();
     itEndOld = pOutput->end();
     itMacro = m_outputArgs->begin();
 
     for (; itOld != itEndOld ; ++itOld, ++itMacro)
     {
-        if ((*itOld)->name_get() != (*itMacro)->name_get())
+        if ((*itOld)->getSymbol() != (*itMacro)->getSymbol())
         {
             return false;
         }
@@ -415,13 +481,13 @@ bool Macro::operator==(const InternalType& it)
 
     ast::Exp* pExp = pRight->getBody();
     ast::SerializeVisitor serialOld(pExp);
-    unsigned char* oldSerial = serialOld.serialize(false);
+    unsigned char* oldSerial = serialOld.serialize(false, false);
     ast::SerializeVisitor serialMacro(m_body);
-    unsigned char* macroSerial = serialMacro.serialize(false);
+    unsigned char* macroSerial = serialMacro.serialize(false, false);
 
     //check buffer length
-    unsigned int oldSize = ((unsigned int*)oldSerial)[0] + sizeof(unsigned int);
-    unsigned int macroSize = ((unsigned int*)macroSerial)[0] + sizeof(unsigned int);
+    unsigned int oldSize = *((unsigned int*)oldSerial);
+    unsigned int macroSize = *((unsigned int*)macroSerial);
     if (oldSize != macroSize)
     {
         free(oldSerial);
@@ -429,11 +495,19 @@ bool Macro::operator==(const InternalType& it)
         return false;
     }
 
-    bool ret = (memcmp(oldSerial, macroSerial, oldSize + sizeof(unsigned int)) == 0);
+    bool ret = (memcmp(oldSerial, macroSerial, oldSize) == 0);
 
     free(oldSerial);
     free(macroSerial);
 
     return ret;
 }
+
+void Macro::add_submacro(const symbol::Symbol& s, Macro* macro)
+{
+    macro->IncreaseRef();
+    symbol::Context* ctx = symbol::Context::getInstance();
+    symbol::Variable* var = ctx->getOrCreate(s);
+    m_submacro[var] = macro;
+}
 }