callstack fixed again 88/21588/2
Cedric Delamarre [Thu, 8 Oct 2020 16:18:24 +0000 (18:18 +0200)]
  * propagate the locations until Overload::call to be able to
    set the good one in the call stack.

Change-Id: I9cfa6ecf2f175a947a5496713b8249c1ddd97867

scilab/modules/ast/includes/ast/runvisitor.hxx
scilab/modules/ast/includes/exps/location.hxx
scilab/modules/ast/includes/types/overload.hxx
scilab/modules/ast/src/cpp/ast/run_CallExp.hpp
scilab/modules/ast/src/cpp/ast/run_MatrixExp.hpp
scilab/modules/ast/src/cpp/ast/run_OpExp.hpp
scilab/modules/ast/src/cpp/ast/runvisitor.cpp
scilab/modules/ast/src/cpp/ast/visitor_common.cpp
scilab/modules/ast/src/cpp/types/overload.cpp
scilab/modules/ast/src/cpp/types/types_tools.cpp
scilab/modules/ast/tests/unit_tests/callstack.tst [new file with mode: 0644]

index 7d89860..118cada 100644 (file)
@@ -389,8 +389,8 @@ public :
     void visitprivate(const ArrayListExp & e);
     void visitprivate(const VarDec & e);
 
-    types::InternalType* callOverloadOpExp(OpExp::Oper _oper, types::InternalType* _paramL, types::InternalType* _paramR);
-    types::InternalType* callOverloadMatrixExp(const std::wstring& strType, types::InternalType* _paramL, types::InternalType* _paramR);
+    types::InternalType* callOverloadOpExp(OpExp::Oper _oper, types::InternalType* _paramL, types::InternalType* _paramR, const Location& _Location);
+    types::InternalType* callOverloadMatrixExp(const std::wstring& strType, types::InternalType* _paramL, types::InternalType* _paramR, const Location& _Location);
 };
 }
 
index 7fa6d26..fa367ab 100644 (file)
@@ -34,8 +34,8 @@ public:
     /** \brief Construct a Location. */
     Location (void)
     {
-        first_line = last_line = -1;
-        first_column = last_column = -1;
+        first_line = last_line = 0;
+        first_column = last_column = 0;
     }
     /** \} */
 
index a145fac..51e8cc4 100644 (file)
@@ -33,12 +33,12 @@ public:
     /**
      */
     static types::Function::ReturnValue generateNameAndCall(const std::wstring& _stFunctionName, types::typed_list &in, int _iRetCount,
-            types::typed_list &out, bool _isOperator = false, bool errorOnUndefined = true);
+            types::typed_list &out, bool _isOperator = false, bool errorOnUndefined = true, const Location& _Location = Location());
 
     /**
      */
     static types::Function::ReturnValue call(const std::wstring& _stFunctionName, types::typed_list &in, int _iRetCount,
-            types::typed_list &out, bool _isOperator = false, bool errorOnUndefined = true);
+            types::typed_list &out, bool _isOperator = false, bool errorOnUndefined = true, const Location& _Location = Location());
 
     static std::wstring getNameFromOper(const int);
 
index 59d3d08..7b7e206 100644 (file)
@@ -225,7 +225,7 @@ void RunVisitorT<T>::visitprivate(const CallExp &e)
             if (pIT->isInvokable() == false)
             {
                 // call overload
-                ret = Overload::call(L"%" + pIT->getShortTypeStr() + L"_e", in, iRetCount, out, true);
+                ret = Overload::call(L"%" + pIT->getShortTypeStr() + L"_e", in, iRetCount, out, true, true, e.getLocation());
             }
             else
             {
@@ -233,7 +233,7 @@ void RunVisitorT<T>::visitprivate(const CallExp &e)
                 if (ret == false && pIT->isUserType())
                 {
                     // call overload
-                    ret = Overload::call(L"%" + pIT->getShortTypeStr() + L"_e", in, iRetCount, out, true);
+                    ret = Overload::call(L"%" + pIT->getShortTypeStr() + L"_e", in, iRetCount, out, true, true, e.getLocation());
                 }
             }
 
@@ -305,7 +305,7 @@ void RunVisitorT<T>::visitprivate(const CallExp &e)
             pListArg->killMe();
         }
     }
-    catch (InternalAbort & ia)
+    catch (const InternalAbort & ia)
     {
         setExpectedSize(iSaveExpectedSize);
         if (pIT != getResult())
index 91cc64b..1babc57 100644 (file)
@@ -113,7 +113,7 @@ void RunVisitorT<T>::visitprivate(const MatrixExp &e)
                         {
                             try
                             {
-                                poRow = callOverloadMatrixExp(L"c", poRow, pIT);
+                                poRow = callOverloadMatrixExp(L"c", poRow, pIT, e.getLocation());
                             }
                             catch (const InternalError& error)
                             {
@@ -140,7 +140,7 @@ void RunVisitorT<T>::visitprivate(const MatrixExp &e)
                     {
                         try
                         {
-                            poRow = callOverloadMatrixExp(L"c", poRow, pIT);
+                            poRow = callOverloadMatrixExp(L"c", poRow, pIT, e.getLocation());
                         }
                         catch (const InternalError& error)
                         {
@@ -192,7 +192,7 @@ void RunVisitorT<T>::visitprivate(const MatrixExp &e)
                 {
                     try
                     {
-                        poRow = callOverloadMatrixExp(L"c", poRow, pGT);
+                        poRow = callOverloadMatrixExp(L"c", poRow, pGT, e.getLocation());
                     }
                     catch (const InternalError& error)
                     {
@@ -285,7 +285,7 @@ void RunVisitorT<T>::visitprivate(const MatrixExp &e)
                 {
                     try
                     {
-                        poRow = callOverloadMatrixExp(L"c", pGTResult, pGT);
+                        poRow = callOverloadMatrixExp(L"c", pGTResult, pGT, e.getLocation());
                     }
                     catch (const InternalError& error)
                     {
@@ -326,7 +326,7 @@ void RunVisitorT<T>::visitprivate(const MatrixExp &e)
             {
                 try
                 {
-                    poResult = callOverloadMatrixExp(L"f", poResult, poRow);
+                    poResult = callOverloadMatrixExp(L"f", poResult, poRow, e.getLocation());
                 }
                 catch (const InternalError& error)
                 {
@@ -344,7 +344,7 @@ void RunVisitorT<T>::visitprivate(const MatrixExp &e)
             {
                 try
                 {
-                    poResult = callOverloadMatrixExp(L"f", pGTResult, pGT);
+                    poResult = callOverloadMatrixExp(L"f", pGTResult, pGT, e.getLocation());
                 }
                 catch (const InternalError& error)
                 {
@@ -402,7 +402,7 @@ void RunVisitorT<T>::visitprivate(const MatrixExp &e)
             {
                 try
                 {
-                    poResult = callOverloadMatrixExp(L"f", pGTResult, pGT);
+                    poResult = callOverloadMatrixExp(L"f", pGTResult, pGT, e.getLocation());
                 }
                 catch (const InternalError& error)
                 {
@@ -442,7 +442,7 @@ void RunVisitorT<T>::visitprivate(const MatrixExp &e)
 }
 
 template<class T>
-types::InternalType* RunVisitorT<T>::callOverloadMatrixExp(const std::wstring& strType, types::InternalType* _paramL, types::InternalType* _paramR)
+types::InternalType* RunVisitorT<T>::callOverloadMatrixExp(const std::wstring& strType, types::InternalType* _paramL, types::InternalType* _paramR, const Location& _location)
 {
     types::typed_list in;
     types::typed_list out;
@@ -458,11 +458,11 @@ types::InternalType* RunVisitorT<T>::callOverloadMatrixExp(const std::wstring& s
     {
         if (_paramR->isGenericType() && _paramR->getAs<types::GenericType>()->getDims() > 2)
         {
-            Ret = Overload::call(L"%hm_" + strType + L"_hm", in, 1, out, true);
+            Ret = Overload::call(L"%hm_" + strType + L"_hm", in, 1, out, true, true, _location);
         }
         else
         {
-            Ret = Overload::call(L"%" + _paramL->getAs<types::List>()->getShortTypeStr() + L"_" + strType + L"_" + _paramR->getAs<types::List>()->getShortTypeStr(), in, 1, out, true);
+            Ret = Overload::call(L"%" + _paramL->getAs<types::List>()->getShortTypeStr() + L"_" + strType + L"_" + _paramR->getAs<types::List>()->getShortTypeStr(), in, 1, out, true, true, _location);
         }
     }
     catch (const InternalError& error)
index 84502e2..f994da2 100644 (file)
@@ -202,7 +202,7 @@ void RunVisitorT<T>::visitprivate(const OpExp &e)
         if (pResult == NULL)
         {
             // We did not have any algorithm matching, so we try to call OverLoad
-            pResult = callOverloadOpExp(e.getOper(), pITL, pITR);
+            pResult = callOverloadOpExp(e.getOper(), pITL, pITR, e.getLocation());
         }
 
         setResult(pResult);
@@ -417,7 +417,7 @@ void RunVisitorT<T>::visitprivate(const LogicalOpExp &e)
                     pITR = pIR->extractFullMatrix();
                 }
             }
-            pResult = callOverloadOpExp(e.getOper(), pITL, pITR);
+            pResult = callOverloadOpExp(e.getOper(), pITL, pITR, e.getLocation());
         }
 
         setResult(pResult);
@@ -459,7 +459,7 @@ void RunVisitorT<T>::visitprivate(const LogicalOpExp &e)
 }
 
 template<class T>
-types::InternalType* RunVisitorT<T>::callOverloadOpExp(OpExp::Oper _oper, types::InternalType* _paramL, types::InternalType* _paramR)
+types::InternalType* RunVisitorT<T>::callOverloadOpExp(OpExp::Oper _oper, types::InternalType* _paramL, types::InternalType* _paramR, const Location& _location)
 {
     types::typed_list in;
     types::typed_list out;
@@ -473,7 +473,7 @@ types::InternalType* RunVisitorT<T>::callOverloadOpExp(OpExp::Oper _oper, types:
         in.push_back(_paramR);
         try
         {
-            types::Callable::ReturnValue ret = Overload::generateNameAndCall(Overload::getNameFromOper(_oper), in, 1, out, true);
+            types::Callable::ReturnValue ret = Overload::generateNameAndCall(Overload::getNameFromOper(_oper), in, 1, out, true, true, _location);
             if(ret == types::Function::Error)
             {
                 throw ast::InternalError(ConfigVariable::getLastErrorMessage());
@@ -487,7 +487,7 @@ types::InternalType* RunVisitorT<T>::callOverloadOpExp(OpExp::Oper _oper, types:
 
         _paramR->DecreaseRef();
         return out[0];
-    } 
+    }
 
     _paramL->IncreaseRef();
     _paramR->IncreaseRef();
@@ -496,7 +496,7 @@ types::InternalType* RunVisitorT<T>::callOverloadOpExp(OpExp::Oper _oper, types:
 
     try
     {
-        types::Callable::ReturnValue ret = Overload::generateNameAndCall(Overload::getNameFromOper(_oper), in, 1, out, true);
+        types::Callable::ReturnValue ret = Overload::generateNameAndCall(Overload::getNameFromOper(_oper), in, 1, out, true, true, _location);
         if(ret == types::Function::Error)
         {
             throw ast::InternalError(ConfigVariable::getLastErrorMessage());
index cb26ce9..bad1233 100644 (file)
@@ -429,7 +429,7 @@ void RunVisitorT<T>::visitprivate(const FieldExp &e)
 
         try
         {
-            Ret = Overload::call(L"%" + stType + L"_e", in, 1, out, true);
+            Ret = Overload::call(L"%" + stType + L"_e", in, 1, out, true, true, e.getLocation());
         }
         catch (const InternalError& ie)
         {
@@ -439,7 +439,7 @@ void RunVisitorT<T>::visitprivate(const FieldExp &e)
                 //tlist/mlist name are truncated to 8 first character
                 if (stType.size() > 8)
                 {
-                    Ret = Overload::call(L"%" + stType.substr(0, 8) + L"_e", in, 1, out, true);
+                    Ret = Overload::call(L"%" + stType.substr(0, 8) + L"_e", in, 1, out, true, true, e.getLocation());
                 }
                 else
                 {
@@ -452,7 +452,7 @@ void RunVisitorT<T>::visitprivate(const FieldExp &e)
                 // TList or Mlist
                 if (pValue->isList())
                 {
-                    Ret = Overload::call(L"%l_e", in, 1, out, true);
+                    Ret = Overload::call(L"%l_e", in, 1, out, true, true, e.getLocation());
                 }
                 else
                 {
@@ -1316,7 +1316,7 @@ void RunVisitorT<T>::visitprivate(const NotExp &e)
         pValue->IncreaseRef();
         in.push_back(pValue);
 
-        types::Callable::ReturnValue Ret = Overload::call(L"%" + pValue->getShortTypeStr() + L"_5", in, 1, out, true);
+        types::Callable::ReturnValue Ret = Overload::call(L"%" + pValue->getShortTypeStr() + L"_5", in, 1, out, true, true, e.getLocation());
 
         if (Ret != types::Callable::OK)
         {
@@ -1382,11 +1382,11 @@ void RunVisitorT<T>::visitprivate(const TransposeExp &e)
         types::Callable::ReturnValue Ret;
         if (bConjug)
         {
-            Ret = Overload::call(L"%" + getResult()->getShortTypeStr() + L"_t", in, 1, out, true);
+            Ret = Overload::call(L"%" + getResult()->getShortTypeStr() + L"_t", in, 1, out, true, true, e.getLocation());
         }
         else
         {
-            Ret = Overload::call(L"%" + getResult()->getShortTypeStr() + L"_0", in, 1, out, true);
+            Ret = Overload::call(L"%" + getResult()->getShortTypeStr() + L"_0", in, 1, out, true, true, e.getLocation());
         }
 
         if (Ret != types::Callable::OK)
@@ -1651,7 +1651,7 @@ void RunVisitorT<T>::visitprivate(const ListExp &e)
             in.push_back(pStep);
             pEnd->IncreaseRef();
             in.push_back(pEnd);
-            Ret = Overload::call(L"%" + pStart->getShortTypeStr() + L"_b_" + pStep->getShortTypeStr(), in, 1, out, true);
+            Ret = Overload::call(L"%" + pStart->getShortTypeStr() + L"_b_" + pStep->getShortTypeStr(), in, 1, out, true, true, e.getLocation());
         }
         else
         {
@@ -1660,7 +1660,7 @@ void RunVisitorT<T>::visitprivate(const ListExp &e)
             pStep->killMe();
             pEnd->IncreaseRef();
             in.push_back(pEnd);
-            Ret = Overload::call(L"%" + pStart->getShortTypeStr() + L"_b_" + pEnd->getShortTypeStr(), in, 1, out, true);
+            Ret = Overload::call(L"%" + pStart->getShortTypeStr() + L"_b_" + pEnd->getShortTypeStr(), in, 1, out, true, true, e.getLocation());
         }
     }
     catch (const InternalError& error)
index e5a924d..d1c5c3b 100644 (file)
@@ -651,7 +651,7 @@ types::InternalType* callOverload(const ast::Exp& e, const std::wstring& _strTyp
     {
         try
         {
-            ret = Overload::call(function_name, in, 1, out);
+            ret = Overload::call(function_name, in, 1, out, false, true, e.getLocation());
         }
         catch (const ast::InternalError& error)
         {
index 003cca8..44a1da2 100644 (file)
@@ -53,20 +53,20 @@ std::wstring Overload::buildOverloadName(const std::wstring& _stFunctionName, ty
     return _stFunctionName;
 }
 
-types::Function::ReturnValue Overload::generateNameAndCall(const std::wstring& _stFunctionName, types::typed_list& in, int _iRetCount, types::typed_list& out, bool _isOperator, bool errorOnUndefined)
+types::Function::ReturnValue Overload::generateNameAndCall(const std::wstring& _stFunctionName, types::typed_list& in, int _iRetCount, types::typed_list& out, bool _isOperator, bool errorOnUndefined, const Location& _Location)
 {
     _iRetCount = std::max(1,_iRetCount);
     std::wstring stFunc = buildOverloadName(_stFunctionName, in, _iRetCount, _isOperator);
     if (symbol::Context::getInstance()->get(symbol::Symbol(stFunc)))
     {
-        return call(stFunc, in, _iRetCount, out, _isOperator);
+        return call(stFunc, in, _iRetCount, out, _isOperator, errorOnUndefined, _Location);
     }
 
     // if overload doesn't existe try with short name
-    std::wstring stFunc2 = buildOverloadName(_stFunctionName, in, _iRetCount, _isOperator, true);
+    std::wstring stFunc2 = buildOverloadName(_stFunctionName, in, _iRetCount, _isOperator, errorOnUndefined);
     if (symbol::Context::getInstance()->get(symbol::Symbol(stFunc)))
     {
-        types::Function::ReturnValue ret = call(stFunc, in, _iRetCount, out, _isOperator);
+        types::Function::ReturnValue ret = call(stFunc, in, _iRetCount, out, _isOperator, errorOnUndefined, _Location);
         if (ret == types::Function::OK && ConfigVariable::getWarningMode())
         {
             char* pstFunc2 = wide_string_to_UTF8(stFunc2.c_str());
@@ -79,10 +79,10 @@ types::Function::ReturnValue Overload::generateNameAndCall(const std::wstring& _
     }
 
     // get exeception with overloading error
-    return call(stFunc, in, _iRetCount, out, _isOperator, errorOnUndefined);
+    return call(stFunc, in, _iRetCount, out, _isOperator, errorOnUndefined, _Location);
 }
 
-types::Function::ReturnValue Overload::call(const std::wstring& _stOverloadingFunctionName, types::typed_list& in, int _iRetCount, types::typed_list& out, bool _isOperator, bool errorOnUndefined)
+types::Function::ReturnValue Overload::call(const std::wstring& _stOverloadingFunctionName, types::typed_list& in, int _iRetCount, types::typed_list& out, bool _isOperator, bool errorOnUndefined, const Location& _location)
 {
     _iRetCount = std::max(1,_iRetCount);
     types::InternalType *pIT = symbol::Context::getInstance()->get(symbol::Symbol(_stOverloadingFunctionName));
@@ -97,23 +97,27 @@ types::Function::ReturnValue Overload::call(const std::wstring& _stOverloadingFu
                 return types::Function::ReturnValue::OK_NoResult;
             }
 
-            char pstError1[512];
+            wchar_t pstError1[512];
             char pstError2[512];
             char *pstFuncName = wide_string_to_UTF8(_stOverloadingFunctionName.c_str());
             wchar_t* pwstError = NULL;
             if (_isOperator)
             {
                 os_sprintf(pstError2, _("check or define function %s for overloading.\n"), pstFuncName);
-                os_sprintf(pstError1, "%s%s", _("Undefined operation for the given operands.\n"), pstError2);
+                wchar_t *tmp = to_wide_string(pstError2);
+                os_swprintf(pstError1, 4096, L"%s%ls", _("Undefined operation for the given operands.\n"), tmp);
+                FREE(tmp);
             }
             else
             {
                 os_sprintf(pstError2, _("  check arguments or define function %s for overloading.\n"), pstFuncName);
-                os_sprintf(pstError1, "%s%s", _("Function not defined for given argument type(s),\n"), pstError2);
+                wchar_t *tmp = to_wide_string(pstError2);
+                os_swprintf(pstError1, 4096, L"%s%ls", _("Function not defined for given argument type(s).\n"), tmp);
+                FREE(tmp);
             }
 
             FREE(pstFuncName);
-            ast::InternalError ie(pstError1);
+            ast::InternalError ie(pstError1, 999, _location);
             ie.SetErrorType(ast::TYPE_EXCEPTION);
             throw ie;
         }
@@ -125,7 +129,12 @@ types::Function::ReturnValue Overload::call(const std::wstring& _stOverloadingFu
             types::optional_list opt;
 
             // add line and function name in where
-            ConfigVariable::where_begin(0, 0, pCall);
+            int iMacroLine = 0;
+            if(_location.first_line)
+            {
+                iMacroLine =  _location.first_line + 1 - ConfigVariable::getMacroFirstLines();
+            }
+            ConfigVariable::where_begin(iMacroLine, _location.first_line, pCall);
 
             types::Function::ReturnValue ret;
             ret = pCall->call(in, opt, _iRetCount, out);
@@ -142,9 +151,7 @@ types::Function::ReturnValue Overload::call(const std::wstring& _stOverloadingFu
     }
     catch (const ast::InternalError& ie)
     {
-        // fill where error with 0 as error line because
-        // an overload is always called from a gateway (native function)
-        ConfigVariable::fillWhereError(0);
+        ConfigVariable::fillWhereError(ie.GetErrorLocation().first_line);
         if (pCall)
         {
             if (ConfigVariable::getLastErrorFunction() == L"")
index 77b074e..8482336 100644 (file)
@@ -839,10 +839,15 @@ int checkIndexesArguments(InternalType* _pRef, typed_list* _pArgsIn, typed_list*
             os_swprintf(szError, bsiz, _W("Invalid index.\n").c_str());
 
             delete[] _piMaxDim;
-            delete[] _piCountDim;
+            if (_piCountDim)
+            {
+                delete[] _piCountDim;
+            }
             cleanIndexesArguments(_pArgsIn, _pArgsOut);
 
-            throw ast::InternalError(szError);
+            // Location(-1,-1,-1,-1): it means the locations are unknown at the throw time,
+            // this can be use to set the locations in the first catch which know them.
+            throw ast::InternalError(szError, 999, Location(-1,-1,-1,-1));
         }
 
         _pArgsOut->push_back(pCurrentArg);
diff --git a/scilab/modules/ast/tests/unit_tests/callstack.tst b/scilab/modules/ast/tests/unit_tests/callstack.tst
new file mode 100644 (file)
index 0000000..84577e8
--- /dev/null
@@ -0,0 +1,90 @@
+// ============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2020 - ESI Group - Delamarre Cedric
+//
+//  This file is distributed under the same license as the Scilab package.
+// ============================================================================
+
+// <-- INTERACTIVE TEST -->
+// Execute blocks one by one and check if the callstack is good.
+
+// block #1
+function subblock1(a)
+    b = a
+    1+1
+    b(0) // will error
+endfunction
+function block1(a)
+    b = a;
+    subblock1(b)
+endfunction
+block1(1)
+// at line     4 of function subblock1
+// at line     3 of function block1
+
+// Invalid index.
+
+
+// block #2
+function block2()
+  a="a string"
+  a(2)=0
+endfunction
+block2()
+// at line     9 of function %s_i_c ( SCI/modules/overloading/macros/%s_i_c.sci line 21 )
+// at line     3 of function block2
+
+// %s_i_c: Non implemented feature.
+
+
+// block #3
+function block3()
+  1+1;
+  "a string"*2
+endfunction
+function r=%c_m_s(a,b)
+  cos("a string")
+end
+block3()
+// in builtin                cos
+// at line     2 of function %c_m_s
+// at line     3 of function block3
+
+// Function not defined for given argument type(s).
+//   check arguments or define function %c_cos for overloading.
+
+
+// block #4
+function block4()
+  1+1
+
+  ["a string", 2]
+endfunction
+function r=%c_c_s(a,b)
+  cos("a string")
+end
+block4()
+// in builtin                cos
+// at line     2 of function %c_c_s
+// at line     4 of function block4
+
+// Function not defined for given argument type(s).
+//   check arguments or define function %c_cos for overloading.
+
+
+// block #5
+function r=%i_cos(a)
+    r=cos("a string")
+endfunction
+
+function block5()
+    cos(int8(2))
+endfunction
+block5()
+// in builtin                cos
+// at line     2 of function %i_cos
+// in builtin                cos
+// at line     2 of function block5
+
+// Function not defined for given argument type(s).
+//   check arguments or define function %c_cos for overloading.
\ No newline at end of file