Manage overloaded functions in where.
[scilab.git] / scilab / modules / ast / src / cpp / types / overload.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2010-2010 - DIGITEO - Bruno JOFRET
4  *
5  *  This file must be used under the terms of the CeCILL.
6  *  This source file is licensed as described in the file COPYING, which
7  *  you should have received as part of this distribution.  The terms
8  *  are also available at
9  *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12
13 extern "C"
14 {
15 #include "stdarg.h"
16 #include "os_string.h"
17 #include "sci_malloc.h"
18 #include "sciprint.h"
19 }
20
21 #include "configvariable.hxx"
22 #include "localization.hxx"
23 #include "callable.hxx"
24 #include "overload.hxx"
25 #include "context.hxx"
26 #include "scilabexception.hxx"
27
28 std::wstring Overload::buildOverloadName(std::wstring _stFunctionName, types::typed_list &in, int /*_iRetCount*/, bool _isOperator, bool _truncated)
29 {
30     std::wstring stType0 = in[0]->getShortTypeStr();
31
32     if (_truncated)
33     {
34         stType0 = stType0.substr(0, 8);
35     }
36
37     switch (in.size())
38     {
39         case 0 :
40             return L"%_" + _stFunctionName;
41         case 2:
42             if (_isOperator)
43             {
44                 return L"%" + stType0 + L"_" + _stFunctionName + L"_" + in[1]->getShortTypeStr();
45             }
46         default:
47             return L"%" + stType0 + L"_" + _stFunctionName;
48     }
49     return _stFunctionName;
50 }
51
52 types::Function::ReturnValue Overload::generateNameAndCall(std::wstring _stFunctionName, types::typed_list &in, int _iRetCount, types::typed_list &out, ast::ConstVisitor *_execMe, bool _isOperator)
53 {
54     std::wstring stFunc = buildOverloadName(_stFunctionName, in, _iRetCount, _isOperator);
55     types::Function::ReturnValue ret = types::Function::Error;
56     try
57     {
58         ret = call(stFunc, in, _iRetCount, out, _execMe, _isOperator);
59     }
60     catch (ast::ScilabError se)
61     {
62         std::wstring stFunc2 = buildOverloadName(_stFunctionName, in, _iRetCount, _isOperator, true);
63         ret = call(stFunc2, in, _iRetCount, out, _execMe, _isOperator);
64         if (ret == types::Function::OK && ConfigVariable::getWarningMode())
65         {
66             char* pstFunc2 = wide_string_to_UTF8(stFunc2.c_str());
67             char* pstFunc = wide_string_to_UTF8(stFunc.c_str());
68             sciprint(_("Warning : please rename your overloaded function\n \"%s\" to \"%s\"\n"), pstFunc2, pstFunc);
69             FREE(pstFunc);
70             FREE(pstFunc2);
71         }
72     }
73     return ret;
74 }
75
76 types::Function::ReturnValue Overload::call(std::wstring _stOverloadingFunctionName, types::typed_list &in, int _iRetCount, types::typed_list &out, ast::ConstVisitor *_execMe, bool _isOperator)
77 {
78     types::InternalType *pIT = symbol::Context::getInstance()->get(symbol::Symbol(_stOverloadingFunctionName));
79
80     if (pIT == NULL || pIT->isCallable() == false)
81     {
82         char pstError1[512];
83         char pstError2[512];
84         char *pstFuncName = wide_string_to_UTF8(_stOverloadingFunctionName.c_str());
85         wchar_t* pwstError = NULL;
86         if (_isOperator)
87         {
88             os_sprintf(pstError2, _("check or define function %s for overloading.\n"), pstFuncName);
89             os_sprintf(pstError1, "%s%s", _("Undefined operation for the given operands.\n"), pstError2);
90             pwstError = to_wide_string(pstError1);
91             std::wstring wstError(pwstError);
92             FREE(pwstError);
93             FREE(pstFuncName);
94             throw ast::ScilabError(wstError, 999, Location());
95         }
96         else
97         {
98             os_sprintf(pstError2, _("  check arguments or define function %s for overloading.\n"), pstFuncName);
99             os_sprintf(pstError1, "%s%s", _("Function not defined for given argument type(s),\n"), pstError2);
100             pwstError = to_wide_string(pstError1);
101             std::wstring wstError(pwstError);
102             FREE(pwstError);
103             FREE(pstFuncName);
104             throw ast::ScilabError(wstError, 999, Location());
105         }
106     }
107     types::Callable *pCall = pIT->getAs<types::Callable>();
108     try
109     {
110         types::optional_list opt;
111
112         // add line and function name in where
113         ConfigVariable::where_begin(0, 0, _stOverloadingFunctionName);
114
115         types::Function::ReturnValue ret = pCall->call(in, opt, _iRetCount, out, _execMe);
116
117         // remove function name in where
118         ConfigVariable::where_end();
119
120         return ret;
121     }
122     catch (ast::ScilabMessage sm)
123     {
124         // remove function name in where
125         ConfigVariable::where_end();
126
127         if (pCall->isMacro() || pCall->isMacroFile())
128         {
129             wchar_t szError[bsiz];
130             os_swprintf(szError, bsiz, _W("at line % 5d of function %ls called by :\n").c_str(), sm.GetErrorLocation().first_line, pCall->getName().c_str());
131             throw ast::ScilabMessage(szError);
132         }
133         else
134         {
135             throw sm;
136         }
137     }
138 }
139
140 std::wstring Overload::getNameFromOper(ast::OpExp::Oper _oper)
141 {
142     switch (_oper)
143     {
144         /* standard operators */
145         case ast::OpExp::plus :
146             return std::wstring(L"a");
147         case ast::OpExp::unaryMinus :
148         case ast::OpExp::minus :
149             return std::wstring(L"s");
150         case ast::OpExp::times :
151             return std::wstring(L"m");
152         case ast::OpExp::rdivide :
153             return std::wstring(L"r");
154         case ast::OpExp::ldivide :
155             return std::wstring(L"l");
156         case ast::OpExp::power :
157             return std::wstring(L"p");
158         /* dot operators */
159         case ast::OpExp::dottimes :
160             return std::wstring(L"x");
161         case ast::OpExp::dotrdivide :
162             return std::wstring(L"d");
163         case ast::OpExp::dotldivide :
164             return std::wstring(L"q");
165         case ast::OpExp::dotpower :
166             return std::wstring(L"j");
167         /* Kron operators */
168         case ast::OpExp::krontimes :
169             return std::wstring(L"k");
170         case ast::OpExp::kronrdivide :
171             return std::wstring(L"y");
172         case ast::OpExp::kronldivide :
173             return std::wstring(L"z");
174         /* Control Operators ??? */
175         case ast::OpExp::controltimes :
176             return std::wstring(L"u");
177         case ast::OpExp::controlrdivide :
178             return std::wstring(L"v");
179         case ast::OpExp::controlldivide :
180             return std::wstring(L"w");
181         case ast::OpExp::eq :
182             return std::wstring(L"o");
183         case ast::OpExp::ne :
184             return std::wstring(L"n");
185         case ast::OpExp::lt :
186             return std::wstring(L"1");
187         case ast::OpExp::le :
188             return std::wstring(L"3");
189         case ast::OpExp::gt :
190             return std::wstring(L"2");
191         case ast::OpExp::ge :
192             return std::wstring(L"4");
193         case ast::OpExp::logicalAnd :
194             return std::wstring(L"h");
195         case ast::OpExp::logicalOr :
196             return std::wstring(L"g");
197         case ast::OpExp::logicalShortCutAnd :
198             return std::wstring(L"h");
199         case ast::OpExp::logicalShortCutOr :
200             return std::wstring(L"g");
201         default :
202             return std::wstring(L"???");
203     }
204 }