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