Merge remote-tracking branch 'origin/master' into jit
[scilab.git] / scilab / modules / ast / src / cpp / types / tlist.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2010-2010 - DIGITEO - Antoine ELIAS
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 #include <cstring>
14 #include <sstream>
15 #include "exp.hxx"
16 #include "string.hxx"
17 #include "list.hxx"
18 #include "tlist.hxx"
19 #include "listundefined.hxx"
20 #include "callable.hxx"
21 #include "polynom.hxx"
22 #include "overload.hxx"
23 #include "configvariable.hxx"
24
25 #ifndef NDEBUG
26 #include "inspector.hxx"
27 #endif
28
29 extern "C"
30 {
31 #include "os_string.h"
32 }
33
34 namespace types
35 {
36 /**
37 ** Constructor & Destructor (public)
38 */
39 TList::TList() : List()
40 {
41 #ifndef NDEBUG
42     Inspector::addItem(this);
43 #endif
44 }
45
46 TList::~TList()
47 {
48 #ifndef NDEBUG
49     Inspector::removeItem(this);
50 #endif
51 }
52
53 /**
54 ** Clone
55 ** Create a new List and Copy all values.
56 */
57 InternalType* TList::clone()
58 {
59     return new TList(this);
60 }
61
62 bool TList::exists(const std::wstring& _sKey)
63 {
64     if (getSize() < 1)
65     {
66         return false;
67     }
68
69     String* pS = getFieldNames();
70
71     //first field is the tlist type
72     for (int i = 1 ; i < pS->getSize() ; i++)
73     {
74         if (wcscmp(pS->get(i), _sKey.c_str()) == 0)
75         {
76             return true;
77         }
78     }
79     return false;
80 }
81
82 bool TList::invoke(typed_list & in, optional_list & /*opt*/, int _iRetCount, typed_list & out, const ast::Exp & e)
83 {
84     if (in.size() == 0)
85     {
86         out.push_back(this);
87         return true;
88     }
89     else if (in.size() == 1)
90     {
91         InternalType * arg = in[0];
92         InternalType * _out = NULL;
93         if (arg->isDouble() || arg->isInt() || arg->isBool() || arg->isImplicitList() || arg->isColon() || arg->isDollar())
94         {
95             _out = List::extract(&in);
96             if (_out == NULL)
97             {
98                 // invalid index
99                 return false;
100             }
101
102             List* pList = _out->getAs<types::List>();
103             for (int i = 0; i < pList->getSize(); i++)
104             {
105                 out.push_back(pList->get(i));
106             }
107
108             delete pList;
109         }
110         else if (arg->isString())
111         {
112             std::list<std::wstring> stFields;
113             String * pString = arg->getAs<types::String>();
114             for (int i = 0; i < pString->getSize(); ++i)
115             {
116                 stFields.push_back(pString->get(i));
117             }
118
119             _out = extractStrings(stFields);
120             if (_out == NULL)
121             {
122                 // invalid index
123                 return false;
124             }
125
126             List* pList = _out->getAs<types::List>();
127             for (int i = 0; i < pList->getSize(); i++)
128             {
129                 out.push_back(pList->get(i));
130             }
131
132             delete pList;
133         }
134         else if (arg->isPoly())
135         {
136             Polynom* pPoly = arg->getAs<Polynom>();
137             SinglePoly* pSinglePoly = pPoly->get(0);
138
139             int iMaxDim = 0;
140             double dblParse = -1 * pSinglePoly->get(0);
141             int iSize = getSize();
142
143             if (pSinglePoly->getRank() < 2 && dblParse >= 0 && dblParse < (double)iSize)
144             {
145                 out.push_back(get(iSize - 1 - dblParse));
146             }
147             else
148             {
149                 return false;
150             }
151         }
152
153         if (out.empty() == false)
154         {
155             return true;
156         }
157     }
158     Callable::ReturnValue ret;
159     // Overload of extraction need
160     // the tlist from where we extract
161     this->IncreaseRef();
162     in.push_back(this);
163
164     std::wstring stType = getShortTypeStr();
165     try
166     {
167         ret = Overload::call(L"%" + stType + L"_e", in, _iRetCount, out);
168     }
169     catch (const ast::InternalError &ie)
170     {
171         try
172         {
173             //to compatibility with scilab 5 code.
174             //tlist/mlist name are truncated to 8 first character
175             if (stType.size() > 8)
176             {
177                 std::wcout << (L"%" + stType.substr(0, 8) + L"_e") << std::endl;
178                 ret = Overload::call(L"%" + stType.substr(0, 8) + L"_e", in, 1, out);
179             }
180             else
181             {
182                 throw ie;
183             }
184         }
185         catch (ast::InternalError & /*se*/)
186         {
187             ret = Overload::call(L"%l_e", in, 1, out);
188         }
189     }
190
191     // Remove this from "in" for keep "in" unchanged.
192     this->DecreaseRef();
193     in.pop_back();
194
195     if (ret == Callable::Error)
196     {
197         throw ast::InternalError(ConfigVariable::getLastErrorMessage(), ConfigVariable::getLastErrorNumber(), e.getLocation());
198     }
199
200     return true;
201 }
202
203 bool TList::extract(const std::wstring & name, InternalType *& out)
204 {
205     if (exists(name))
206     {
207         out = getField(name);
208         return true;
209     }
210
211     return false;
212 }
213
214 InternalType* TList::getField(const std::wstring& _sKey)
215 {
216     return List::get(getIndexFromString(_sKey));
217 }
218
219 int TList::getIndexFromString(const std::wstring& _sKey)
220 {
221     if (getSize() < 1)
222     {
223         return -1;
224     }
225
226     String* pS = getFieldNames();
227     //first field is the tlist type
228     for (int i = 1 ; i < pS->getSize() ; i++)
229     {
230         if (wcscmp(pS->get(i), _sKey.c_str()) == 0)
231         {
232             return i;
233         }
234     }
235     return -1;
236 }
237
238 InternalType* TList::extractStrings(const std::list<std::wstring>& _stFields)
239 {
240     int i = 0;
241     List* pLResult = new List();
242     std::list<std::wstring>::const_iterator it;
243     for (it = _stFields.begin() ; it != _stFields.end() ; it++)
244     {
245         if (exists(*it) == false)
246         {
247             return pLResult;
248         }
249     }
250
251     for (it = _stFields.begin() ; it != _stFields.end() ; it++, i++)
252     {
253         InternalType* pIT = getField(*it);
254         if (pIT == NULL)
255         {
256             delete pLResult;
257             return NULL;
258         }
259
260         pLResult->set(i, pIT);
261     }
262
263     return pLResult;
264 }
265
266 std::wstring TList::getTypeStr()
267 {
268     if (getSize() < 1)
269     {
270         return L"";
271     }
272
273     return getFieldNames()->get(0);
274 }
275
276 std::wstring TList::getShortTypeStr()
277 {
278     return getTypeStr();
279 }
280
281 bool TList::set(const std::wstring& _sKey, InternalType* _pIT)
282 {
283     return List::set(getIndexFromString(_sKey), _pIT);
284 }
285
286 bool TList::set(const int _iIndex, InternalType* _pIT)
287 {
288     return List::set(_iIndex, _pIT);
289 }
290
291 String* TList::getFieldNames()
292 {
293     return (*m_plData)[0]->getAs<types::String>();
294 }
295
296 /**
297 ** toString to display TLists
298 */
299 bool TList::toString(std::wostringstream& ostr)
300 {
301     //call overload %type_p if exists
302     types::typed_list in;
303     types::typed_list out;
304
305     IncreaseRef();
306     in.push_back(this);
307
308     try
309     {
310         if (Overload::generateNameAndCall(L"p", in, 1, out) == Function::Error)
311         {
312             ConfigVariable::setError();
313         }
314
315         ostr.str(L"");
316         DecreaseRef();
317         return true;
318     }
319     catch (ast::InternalError& e)
320     {
321         if (e.GetErrorType() == ast::TYPE_ERROR)
322         {
323             DecreaseRef();
324             throw e;
325         }
326
327         // avoid error message about undefined overload %type_p
328         ConfigVariable::resetError();
329     }
330
331     DecreaseRef();
332
333     // special case for lss
334     if (getSize() != 0 &&
335             (*m_plData)[0]->isString() &&
336             (*m_plData)[0]->getAs<types::String>()->getSize() > 0 &&
337             wcscmp((*m_plData)[0]->getAs<types::String>()->get(0), L"lss") == 0)
338     {
339         wchar_t* wcsVarName = os_wcsdup(ostr.str().c_str());
340         int iPosition = 1;
341         const wchar_t * wcsDesc[7] = {L"  (state-space system:)", L"= A matrix =", L"= B matrix =", L"= C matrix =", L"= D matrix =", L"= X0 (initial state) =", L"= Time domain ="};
342         for (auto val : *m_plData)
343         {
344             std::wostringstream nextVarName;
345             ostr.str(L"");
346             nextVarName << " " << wcsVarName << L"(" << iPosition << L")";
347             ostr << std::endl << nextVarName.str() << wcsDesc[iPosition - 1] << std::endl << std::endl;
348             scilabWriteW(ostr.str().c_str());
349             VariableToString(val, nextVarName.str().c_str());
350             iPosition++;
351         }
352         ostr.str(L"");
353         free(wcsVarName);
354         return true;
355     }
356
357     // call normal toString
358     return List::toString(ostr);
359 }
360 } // end namespace types