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