Merge remote-tracking branch 'origin/master' into jit
[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 "opexp.hxx"
27 #include "execvisitor.hxx"
28
29 std::wstring Overload::buildOverloadName(const std::wstring& _stFunctionName, types::typed_list &in, int /*_iRetCount*/, bool _isOperator, bool _truncated)
30 {
31     std::wstring stType0 = in[0]->getShortTypeStr();
32
33     if (_truncated)
34     {
35         stType0 = stType0.substr(0, 8);
36     }
37
38     switch (in.size())
39     {
40         case 0 :
41             return L"%_" + _stFunctionName;
42         case 2:
43             if (_isOperator)
44             {
45                 return L"%" + stType0 + L"_" + _stFunctionName + L"_" + in[1]->getShortTypeStr();
46             }
47         default:
48             return L"%" + stType0 + L"_" + _stFunctionName;
49     }
50     return _stFunctionName;
51 }
52
53 types::Function::ReturnValue Overload::generateNameAndCall(const std::wstring& _stFunctionName, types::typed_list &in, int _iRetCount, types::typed_list &out, bool _isOperator)
54 {
55     std::wstring stFunc = buildOverloadName(_stFunctionName, in, _iRetCount, _isOperator);
56     if (symbol::Context::getInstance()->get(symbol::Symbol(stFunc)))
57     {
58         return call(stFunc, in, _iRetCount, out, _isOperator);
59     }
60
61     // if overload doesn't existe try with short name
62     std::wstring stFunc2 = buildOverloadName(_stFunctionName, in, _iRetCount, _isOperator, true);
63     if (symbol::Context::getInstance()->get(symbol::Symbol(stFunc)))
64     {
65         types::Function::ReturnValue ret = call(stFunc, in, _iRetCount, out, _isOperator);
66         if (ret == types::Function::OK && ConfigVariable::getWarningMode())
67         {
68             char* pstFunc2 = wide_string_to_UTF8(stFunc2.c_str());
69             char* pstFunc = wide_string_to_UTF8(stFunc.c_str());
70             sciprint(_("Warning : please rename your overloaded function\n \"%s\" to \"%s\"\n"), pstFunc2, pstFunc);
71             FREE(pstFunc);
72             FREE(pstFunc2);
73         }
74         return ret;
75     }
76
77     // get exeception with overloading error
78     return call(stFunc, in, _iRetCount, out, _isOperator);
79 }
80
81 types::Function::ReturnValue Overload::call(const std::wstring& _stOverloadingFunctionName, types::typed_list &in, int _iRetCount, types::typed_list &out, bool _isOperator)
82 {
83     types::InternalType *pIT = symbol::Context::getInstance()->get(symbol::Symbol(_stOverloadingFunctionName));
84     types::Callable *pCall = NULL;
85     try
86     {
87         if (pIT == NULL || pIT->isCallable() == false)
88         {
89             char pstError1[512];
90             char pstError2[512];
91             char *pstFuncName = wide_string_to_UTF8(_stOverloadingFunctionName.c_str());
92             wchar_t* pwstError = NULL;
93             if (_isOperator)
94             {
95                 os_sprintf(pstError2, _("check or define function %s for overloading.\n"), pstFuncName);
96                 os_sprintf(pstError1, "%s%s", _("Undefined operation for the given operands.\n"), pstError2);
97             }
98             else
99             {
100                 os_sprintf(pstError2, _("  check arguments or define function %s for overloading.\n"), pstFuncName);
101                 os_sprintf(pstError1, "%s%s", _("Function not defined for given argument type(s),\n"), pstError2);
102             }
103
104             FREE(pstFuncName);
105             ast::InternalError ie(pstError1);
106             ie.SetErrorType(ast::TYPE_EXCEPTION);
107             throw ie;
108         }
109
110         if (ConfigVariable::increaseRecursion())
111         {
112             pCall = pIT->getAs<types::Callable>();
113
114             types::optional_list opt;
115
116             // add line and function name in where
117             ConfigVariable::where_begin(0, 0, pCall);
118
119             types::Function::ReturnValue ret;
120             ret = pCall->call(in, opt, _iRetCount, out);
121
122             // remove function name in where
123             ConfigVariable::where_end();
124             ConfigVariable::decreaseRecursion();
125             return ret;
126         }
127         else
128         {
129             throw ast::RecursionException();
130         }
131     }
132     catch (ast::InternalError ie)
133     {
134         ConfigVariable::fillWhereError(ie.GetErrorLocation().first_line);
135         if (pCall)
136         {
137             if (ConfigVariable::getLastErrorFunction() == L"")
138             {
139                 ConfigVariable::setLastErrorFunction(pCall->getName());
140                 ConfigVariable::setLastErrorLine(ie.GetErrorLocation().first_line);
141             }
142
143             // remove function name in where
144             ConfigVariable::where_end();
145             ConfigVariable::decreaseRecursion();
146         }
147
148         throw ie;
149     }
150 }
151
152 std::wstring Overload::getNameFromOper(const int _oper)
153 {
154     switch (_oper)
155     {
156         /* standard operators */
157         case ast::OpExp::plus :
158             return std::wstring(L"a");
159         case ast::OpExp::unaryMinus :
160         case ast::OpExp::minus :
161             return std::wstring(L"s");
162         case ast::OpExp::times :
163             return std::wstring(L"m");
164         case ast::OpExp::rdivide :
165             return std::wstring(L"r");
166         case ast::OpExp::ldivide :
167             return std::wstring(L"l");
168         case ast::OpExp::power :
169             return std::wstring(L"p");
170         /* dot operators */
171         case ast::OpExp::dottimes :
172             return std::wstring(L"x");
173         case ast::OpExp::dotrdivide :
174             return std::wstring(L"d");
175         case ast::OpExp::dotldivide :
176             return std::wstring(L"q");
177         case ast::OpExp::dotpower :
178             return std::wstring(L"j");
179         /* Kron operators */
180         case ast::OpExp::krontimes :
181             return std::wstring(L"k");
182         case ast::OpExp::kronrdivide :
183             return std::wstring(L"y");
184         case ast::OpExp::kronldivide :
185             return std::wstring(L"z");
186         /* Control Operators ??? */
187         case ast::OpExp::controltimes :
188             return std::wstring(L"u");
189         case ast::OpExp::controlrdivide :
190             return std::wstring(L"v");
191         case ast::OpExp::controlldivide :
192             return std::wstring(L"w");
193         case ast::OpExp::eq :
194             return std::wstring(L"o");
195         case ast::OpExp::ne :
196             return std::wstring(L"n");
197         case ast::OpExp::lt :
198             return std::wstring(L"1");
199         case ast::OpExp::le :
200             return std::wstring(L"3");
201         case ast::OpExp::gt :
202             return std::wstring(L"2");
203         case ast::OpExp::ge :
204             return std::wstring(L"4");
205         case ast::OpExp::logicalAnd :
206             return std::wstring(L"h");
207         case ast::OpExp::logicalOr :
208             return std::wstring(L"g");
209         case ast::OpExp::logicalShortCutAnd :
210             return std::wstring(L"h");
211         case ast::OpExp::logicalShortCutOr :
212             return std::wstring(L"g");
213         default :
214             return std::wstring(L"???");
215     }
216 }