macro print fixed.
[scilab.git] / scilab / modules / ast / src / cpp / types / types_tools.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2011 - 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 "alltypes.hxx"
14 #include "types_tools.hxx"
15 #include "overload.hxx"
16 #include "execvisitor.hxx"
17 extern "C"
18 {
19 #include "os_swprintf.h"
20 }
21
22 namespace types
23 {
24 //check argument types and compute, dimensions, count of combinations, max indexes
25 int checkIndexesArguments(InternalType* _pRef, typed_list* _pArgsIn, typed_list* _pArgsOut, int* _piMaxDim, int* _piCountDim)
26 {
27     int iDims           = static_cast<int>(_pArgsIn->size());
28     int iSeqCount       = 1;
29     bool bUndefine      = false;
30
31     for (int i = 0 ; i < iDims ; i++)
32     {
33         bool bDeleteNeeded  = false;
34         InternalType* pIT = (*_pArgsIn)[i];
35         Double *pCurrentArg = NULL;
36
37         if (pIT->isDouble())
38         {
39             pCurrentArg = pIT->getAs<Double>();
40             if (pCurrentArg->isEmpty())
41             {
42                 return 0;
43             }
44
45             if (pCurrentArg->isIdentity())
46             {
47                 //extract with eye() <=> :
48                 pIT = new Colon();
49                 bDeleteNeeded = true;
50             }
51         }
52
53         if (pIT->isColon() || pIT->isImplicitList())
54         {
55             //: or a:b:c
56             ImplicitList* pIL = pIT->getAs<ImplicitList>()->clone()->getAs<ImplicitList>();
57             if (pIL->isComputable() == false)
58             {
59                 //: or $
60                 if (_pRef == NULL)
61                 {
62                     //not enough information to compute indexes.
63                     _pArgsOut->push_back(NULL);
64                     bUndefine = true;
65                     pIL->killMe();;
66                     continue;
67                 }
68                 //evalute polynom with "MaxDim"
69                 int iMaxDim = _pRef->getAs<GenericType>()->getVarMaxDim(i, iDims);
70 #if defined(_SCILAB_DEBUGREF_)
71                 Double* pdbl = new Double(iMaxDim);
72 #else
73                 Double dbl(iMaxDim);
74 #endif
75                 if (pIL->getStart()->isPoly())
76                 {
77                     Polynom *poPoly     = pIL->getStart()->getAs<types::Polynom>();
78 #if defined(_SCILAB_DEBUGREF_)
79                     pIL->setStart(poPoly->evaluate(pdbl));
80 #else
81                     pIL->setStart(poPoly->evaluate(&dbl));
82 #endif
83                 }
84                 if (pIL->getStep()->isPoly())
85                 {
86                     Polynom *poPoly     = pIL->getStep()->getAs<types::Polynom>();
87 #if defined(_SCILAB_DEBUGREF_)
88                     pIL->setStep(poPoly->evaluate(pdbl));
89 #else
90                     pIL->setStep(poPoly->evaluate(&dbl));
91 #endif
92                 }
93                 if (pIL->getEnd()->isPoly())
94                 {
95                     Polynom *poPoly     = pIL->getEnd()->getAs<types::Polynom>();
96 #if defined(_SCILAB_DEBUGREF_)
97                     pIL->setEnd(poPoly->evaluate(pdbl));
98 #else
99                     pIL->setEnd(poPoly->evaluate(&dbl));
100 #endif
101                 }
102
103 #if defined(_SCILAB_DEBUGREF_)
104                 pdbl->killMe();
105 #endif
106             }
107
108
109             pCurrentArg = pIL->extractFullMatrix()->getAs<Double>();
110             pIL->killMe();
111         }
112         else if (pIT->isString())
113         {
114             String* pStr = pIT->getAs<String>();
115             if (_pRef->isStruct())
116             {
117                 Struct* pStruct = _pRef->getAs<Struct>();
118
119                 if (_pArgsIn->size() != 1 || pStr->isScalar() == false)
120                 {
121                     bUndefine = true;
122                     continue;
123                 }
124
125                 wchar_t* pFieldName = pStr->get(0);
126
127                 // pCurrent arg is indexed to 1 unlike the return of "getFieldIndex"
128                 int iIndex = pStruct->get(0)->getFieldIndex(pFieldName) + 1;
129                 if (iIndex == -1)
130                 {
131                     bUndefine = true;
132                     continue;
133                 }
134
135                 pCurrentArg = new Double((double)iIndex);
136             }
137             else if (_pRef->isTList())
138             {
139                 // List cant be extract by field and MList must call overload
140                 TList* pTL = _pRef->getAs<TList>();
141                 pCurrentArg = new Double(pStr->getDims(), pStr->getDimsArray());
142                 double* pdbl = pCurrentArg->get();
143                 for (int i = 0; i < pStr->getSize(); i++)
144                 {
145                     wchar_t* pFieldName = pStr->get(i);
146                     int iIndex = pTL->getIndexFromString(pFieldName);
147                     if (iIndex == -1)
148                     {
149                         bUndefine = true;
150                         continue;
151                     }
152                     pdbl[i] = (double)(iIndex + 1);
153                 }
154             }
155             else if (_pRef->isCell())
156             {
157             }
158             else
159             {
160                 bUndefine = true;
161                 break;
162             }
163         }
164         else if (pIT->isPoly())
165         {
166             //$
167             Polynom* pMP = pIT->getAs<types::Polynom>();
168             int iMaxDim     = 0;
169             //if pRef == NULL, use 0 insteadof, to allow a($+1) on new variable
170             if (_pRef)
171             {
172                 iMaxDim     = _pRef->getAs<GenericType>()->getVarMaxDim(i, iDims);
173             }
174
175 #ifdef _SCILAB_DEBUGREF_
176             Double* pdbl = new Double(iMaxDim); // $
177             pCurrentArg = pMP->evaluate(pdbl);
178             pdbl->killMe();
179 #else
180             Double dbl(iMaxDim); // $
181             pCurrentArg = pMP->evaluate(&dbl);
182 #endif
183         }
184         else if (pIT->isBool())
185         {
186             //[T F F T F]
187             Bool *pB    = pIT->getAs<types::Bool>();
188             int *piB    = pB->get();
189             const int size = pB->getSize();
190
191             //find true item count
192             int iItemCount = 0;
193             for (int j = 0 ; j < size; j++)
194             {
195                 if (piB[j])
196                 {
197                     iItemCount++;
198                 }
199             }
200
201             //allow new Double variable
202             Double* pDbl    = new Double(1, iItemCount);
203             double* pdbl    = pDbl->getReal();
204
205             int j = 0;
206             for (int l = 0 ; l < size; l++)
207             {
208                 if (piB[l])
209                 {
210                     pdbl[j++] = l + 1;
211                 }
212             }
213             pCurrentArg = pDbl;
214         }
215
216         if (bDeleteNeeded)
217         {
218             pIT->killMe();
219         }
220
221         if (pCurrentArg)
222         {
223             const int iCountDim = pCurrentArg->getSize();
224             _piMaxDim[i] = 0;
225             for (int j = 0 ; j < iCountDim ; j++)
226             {
227                 //checks if size < size(int)
228                 if (pCurrentArg->get(j) >= INT_MAX)
229                 {
230                     wchar_t szError[bsiz];
231                     os_swprintf(szError, bsiz, _W("variable size exceeded : less than %d expected.\n").c_str(), INT_MAX);
232                     throw ast::ScilabError(szError);
233                 }
234
235                 const int d = static_cast<int>(pCurrentArg->get(j));
236                 if (d > _piMaxDim[i])
237                 {
238                     _piMaxDim[i] = d;
239                 }
240             }
241
242             iSeqCount *= iCountDim;
243             if (_piCountDim)
244             {
245                 _piCountDim[i] = iCountDim;
246             }
247         }
248
249         _pArgsOut->push_back(pCurrentArg);
250
251     }
252
253     //returns a negative value if at least one parameter is undefined
254     //case with : or $ for creation by insertion
255     return (!bUndefine ? iSeqCount : - iSeqCount);
256 }
257
258 void cleanIndexesArguments(typed_list* _pArgsOrig, typed_list* _pArgsNew)
259 {
260     //free pArg content
261     for (int iArg = 0; iArg < _pArgsNew->size(); iArg++)
262     {
263         if ((*_pArgsNew)[iArg] != (*_pArgsOrig)[iArg])
264         {
265             (*_pArgsNew)[iArg]->killMe();
266         }
267     }
268
269     _pArgsNew->clear();
270 }
271
272 void getIndexesWithDims(int _iIndex, int* _piIndexes, int* _piDims, int _iDims)
273 {
274     int iMul = 1;
275     for (int i = 0 ; i < _iDims ; i++)
276     {
277         _piIndexes[i] = (int)(_iIndex / iMul) % _piDims[i];
278         iMul *= _piDims[i];
279     }
280
281     //matrix [2,4,3]
282     //index = 12 ( 0,2,1) = 1 * 4 * 2 + 2 * 2 + 0 = 12
283     //loop 1
284     // (12 / 1) % 2 -> 0
285     //loop 2
286     // (12 / 2) % 4 -> 2
287     //loop 3
288     // (12 / 8) % 3 -> 1
289
290     //matrix [3,4,3]
291     //index = 22
292     //loop 1
293     // (22 / 1) % 3 -> 1
294     //loop 2
295     // (22 / 3) % 4 -> 3
296     //loop 3
297     // (22 / 12) % 3 -> 1
298
299     //matrix [3,4,3]
300     //index = 35
301     //loop 1
302     // (35 / 1) % 3 -> 2
303     //loop 2
304     // (35 / 3) % 4 -> 3
305     //loop 3
306     // (35 / 12) % 3 -> 2
307 }
308
309
310 int getIndexWithDims(int* _piIndexes, int* _piDims, int _iDims)
311 {
312     int idx = 0;
313     int iMult = 1;
314     for (int i = 0 ; i < _iDims ; i++)
315     {
316         idx += _piIndexes[i] * iMult;
317         iMult *= _piDims[i];
318     }
319     return idx;
320 }
321
322 types::Function::ReturnValue VariableToString(types::InternalType* pIT, const wchar_t* wcsVarName)
323 {
324     if (pIT->hasToString() == false)
325     {
326         types::Function::ReturnValue ret = types::Function::Error;
327         //call overload %type_p
328         types::typed_list in;
329         types::typed_list out;
330         ast::ExecVisitor* exec = new ast::ExecVisitor();
331
332         pIT->IncreaseRef();
333         in.push_back(pIT);
334
335         try
336         {
337             ret = Overload::generateNameAndCall(L"p", in, 1, out, exec);
338             delete exec;
339             pIT->DecreaseRef();
340             return ret;
341         }
342         catch (ast::ScilabError &e)
343         {
344             delete exec;
345             pIT->DecreaseRef();
346             throw e;
347         }
348     }
349     else
350     {
351         std::wostringstream ostr;
352         if (pIT->isList() || pIT->isCallable())
353         {
354             ostr << wcsVarName;
355         }
356
357         //to manage lines information
358         int iLines = ConfigVariable::getConsoleLines();
359
360         bool bFinish = false;
361         do
362         {
363             //block by block
364             bFinish = pIT->toString(ostr);
365             if (ConfigVariable::isError())
366             {
367                 ConfigVariable::resetError();
368                 ostr.str(L"");
369                 return types::Function::Error;
370             }
371
372             if (bFinish == false && iLines != 0)
373             {
374                 //show message on prompt
375                 bFinish = linesmore() == 1;
376             }
377
378             scilabForcedWriteW(ostr.str().c_str());
379             ostr.str(L"");
380         }
381         while (bFinish == false);
382
383         pIT->clearPrintState();
384         return types::Function::OK;
385     }
386 }
387 }