2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2014 - Scilab Enterprises - Antoine ELIAS
5 * Copyright (C) 2012 - 2016 - Scilab Enterprises
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.
16 //file included in runvisitor.cpp
20 void RunVisitorT<T>::visitprivate(const CallExp &e)
22 CoverageInstance::invokeAndStartChrono((void*)&e);
23 types::typed_list outTmp;
24 types::typed_list inTmp;
25 std::vector<std::wstring> vectOptName;
26 std::vector<int> vectNbResult;
28 int iRetCount = getExpectedSize();
29 int iSaveExpectedSize = iRetCount;
31 //get function arguments
32 exps_t args = e.getArgs();
33 getInputs(e, args, inTmp, vectOptName, vectNbResult);
35 // reset expected size for recursive call
36 // ie [a, b] = l(1)(1), where l is a list containing a function with two output argument
38 // get function/variable
41 e.getName().accept(*this);
43 catch (ScilabException &)
45 cleanIn(inTmp, outTmp);
46 CoverageInstance::stopChrono((void*)&e);
49 setExpectedSize(iSaveExpectedSize);
51 types::InternalType* pIT = getResult();
53 // pIT can be NULL if one of call return nothing. foo()(1) with foo return nothing.
57 cleanIn(inTmp, outTmp);
58 std::wostringstream os;
59 os << _W("Cannot extract from nothing.") << std::endl;
60 CoverageInstance::stopChrono((void*)&e);
61 throw ast::InternalError(os.str(), 999, e.getLocation());
64 types::typed_list out;
66 types::optional_list opt;
71 // getInvokeNbOut will parse the file in case of macrofile
72 // this could throw an exception
73 iInvokeNbOut = pIT->getInvokeNbOut();
75 catch (const InternalError& ie)
78 cleanIn(inTmp, outTmp);
79 CoverageInstance::stopChrono((void*)&e);
83 // manage case [a,b]=foo() where foo is defined as a=foo()
84 if (iInvokeNbOut != -1 && iInvokeNbOut < iRetCount)
87 cleanIn(inTmp, outTmp);
88 std::wostringstream os;
89 os << _W("Wrong number of output arguments.\n") << std::endl;
90 CoverageInstance::stopChrono((void*)&e);
91 throw ast::InternalError(os.str(), 999, e.getLocation());
94 if (pIT->isCallable())
96 CoverageInstance::invoke(static_cast<types::Callable *>(pIT));
99 // manage input according the function/variable
103 for (auto& arg : args)
107 //special case for empty extraction of list ( list()(:) )
108 if (vectNbResult[iLoop] == 0)
113 //extract implicit list for call()
114 if (pIT->isCallable() || pIT->isUserType())
116 if (inTmp[iterIn]->isImplicitList())
118 types::ImplicitList* pIL = inTmp[iterIn]->getAs<types::ImplicitList>();
119 if (pIL->isComputable())
121 types::InternalType* pITExtract = pIL->extractFullMatrix();
122 pITExtract->IncreaseRef();
123 inTmp[iterIn] = pITExtract;
130 // management of optional input
131 if (arg->isAssignExp())
133 if (pIT->hasInvokeOption())
135 opt[vectOptName[iterOptName]] = inTmp[iterIn];
137 //in case of macro/macrofile, we have to shift input param
138 //so add NULL item in in list to keep initial order
139 if (pIT->isMacro() || pIT->isMacroFile())
141 in.push_back(new types::ListInsert(new types::String(vectOptName[iterOptName].data())));
149 in.push_back(inTmp[iterIn++]);
156 for (int i = 0; i < vectNbResult[iLoop]; i++, iterIn++)
158 in.push_back(inTmp[iterIn]);
164 // Extraction with a List in input argument.
165 // This extraction must be a recursive extract.
167 types::List* pListArg = NULL;
168 if (pIT->isCallable() == false && in.size() == 1 && in[0]->isList())
170 pListArg = in[0]->getAs<types::List>();
171 iLoopSize = pListArg->getSize();
175 setExpectedSize(iSaveExpectedSize);
177 // override iRetCount only in relevant cases
178 if (pIT->isCallable() && e.getParent()->isSeqExp())
180 iRetCount = std::max(0, iRetCount);
184 iRetCount = std::max(1, iRetCount);
187 for (int i = 0; i < iLoopSize; i++)
191 in[0] = pListArg->get(i);
195 if (pIT->isCallable())
197 // list used like "varargin"
198 types::List* pLFuncArgs = in[0]->getAs<types::List>();
199 types::typed_list input;
200 for (int j = 0; j < pLFuncArgs->getSize(); j++)
202 input.push_back(pLFuncArgs->get(j));
203 input.back()->IncreaseRef();
210 pListArg->DecreaseRef();
213 std::wostringstream os;
214 os << _W("Invalid index.\n");
215 throw ast::InternalError(os.str(), 999, e.getFirstLocation());
220 in[0]->IncreaseRef();
225 if (pIT->isInvokable() == false)
228 ret = Overload::call(L"%" + pIT->getShortTypeStr() + L"_e", in, iRetCount, out, true);
232 ret = pIT->invoke(in, opt, iRetCount, out, e);
233 if (ret == false && pIT->isUserType())
236 ret = Overload::call(L"%" + pIT->getShortTypeStr() + L"_e", in, iRetCount, out, true);
242 if (iSaveExpectedSize != -1 && iSaveExpectedSize > out.size())
245 if (pIT->isCallable())
247 char* strFName = wide_string_to_UTF8(pIT->getAs<types::Callable>()->getName().c_str());
248 os_sprintf(szError, _("%s: Wrong number of output argument(s): %d expected.\n"), strFName, out.size());
253 os_sprintf(szError, _("%s: Wrong number of output argument(s): %d expected.\n"), "extract", out.size());
256 wchar_t* wError = to_wide_string(szError);
257 std::wstring err(wError);
259 throw InternalError(err, 999, e.getLocation());
262 setExpectedSize(iSaveExpectedSize);
267 // In case a.b(), getResult contain pIT ("b").
268 // If out == pIT, do not delete it.
269 if (getResult() != pIT)
271 // protect element of out in case where
272 // out contain elements of pIT
273 for (int i = 0; i < out.size(); i++)
275 out[i]->IncreaseRef();
281 for (int i = 0; i < out.size(); i++)
283 out[i]->DecreaseRef();
287 if (pListArg && i + 1 != iLoopSize)
296 std::wostringstream os;
297 os << _W("Invalid index.\n");
298 throw ast::InternalError(os.str(), 999, e.getFirstLocation());
304 pListArg->DecreaseRef();
308 catch (InternalAbort & ia)
310 setExpectedSize(iSaveExpectedSize);
311 if (pIT != getResult())
319 CoverageInstance::stopChrono((void*)&e);
323 catch (const InternalError& ie)
325 setExpectedSize(iSaveExpectedSize);
326 if (pIT != getResult())
334 CoverageInstance::stopChrono((void*)&e);
339 CoverageInstance::stopChrono((void*)&e);
343 void RunVisitorT<T>::visitprivate(const CellCallExp &e)
345 CoverageInstance::invokeAndStartChrono((void*)&e);
351 e.getName().accept(execMeCell);
353 catch (ScilabException &)
355 CoverageInstance::stopChrono((void*)&e);
359 if (execMeCell.getResult() != NULL)
361 //a{xxx} with a variable, extraction
362 types::InternalType *pIT = NULL;
364 pIT = execMeCell.getResult();
369 if (pIT->isCell() == false)
371 CoverageInstance::stopChrono((void*)&e);
372 throw ast::InternalError(_W("[error] Cell contents reference from a non-cell array object.\n"), 999, e.getFirstLocation());
375 //Create list of indexes
376 ast::exps_t exps = e.getArgs();
377 types::typed_list *pArgs = GetArgumentList(exps);
379 if (pArgs->size() == 0)
383 std::wostringstream os;
384 os << _W("Cell : Cannot extract without arguments.\n");
385 CoverageInstance::stopChrono((void*)&e);
386 throw ast::InternalError(os.str(), 999, e.getFirstLocation());
389 types::List* pList = pIT->getAs<types::Cell>()->extractCell(pArgs);
394 std::wostringstream os;
395 os << _W("inconsistent row/column dimensions\n");
396 //os << ((*e.args_get().begin())->getLocation()).getLocationString() << std::endl;
397 CoverageInstance::stopChrono((void*)&e);
398 throw ast::InternalError(os.str(), 999, e.getFirstLocation());
401 if (pList->getSize() == 1)
403 types::InternalType* ret = pList->get(0);
416 //clean pArgs return by GetArgumentList
417 for (int iArg = 0; iArg < (int)pArgs->size(); iArg++)
419 (*pArgs)[iArg]->killMe();
426 //result == NULL ,variable doesn't exist :(
427 // Should never be in this case
428 // In worst case variable pointing to function does not exists
429 // visitprivate(SimpleVar) will throw the right exception.
431 CoverageInstance::stopChrono((void*)&e);
434 void RunVisitor::getInputs(const CallExp& e, exps_t& args, types::typed_list& inTmp, std::vector<std::wstring>& vectOptName, std::vector<int>& vectNbResult)
438 for (auto& arg : args)
440 int iSize = getExpectedSize();
441 if (arg->isAssignExp())
443 AssignExp* pAssign = static_cast<AssignExp*>(arg);
445 Exp* pL = &pAssign->getLeftExp();
446 if (!pL->isSimpleVar())
448 std::wostringstream os;
449 os << _W("left side of optional parameter must be a variable") << std::endl;
450 CoverageInstance::stopChrono((void*)&e);
451 throw ast::InternalError(os.str(), 999, e.getLocation());
454 SimpleVar* pVar = pL->getAs<SimpleVar>();
455 Exp* pR = &pAssign->getRightExp();
456 // optional parameter have only one output argument
462 catch (ScilabException &)
464 CoverageInstance::stopChrono((void*)&e);
467 setExpectedSize(iSize);
468 types::InternalType* pITR = getResult();
469 // IncreaseRef to protect opt argument of scope_end delete
470 // It will be deleted by clear_opt
473 vectOptName.push_back(pVar->getSymbol().getName());
474 inTmp.push_back(pITR);
475 vectNbResult.push_back(1);
486 catch (ScilabException &)
488 CoverageInstance::stopChrono((void*)&e);
491 setExpectedSize(iSize);
493 if (getResult() == NULL)
495 //special case for empty extraction of list ( list()(:) )
496 vectNbResult.push_back(0);
500 if (isSingleResult())
502 inTmp.push_back(getResult());
503 getResult()->IncreaseRef();
507 for (int i = 0; i < getResultSize(); i++)
509 types::InternalType * pITArg = getResult(i);
510 pITArg->IncreaseRef();
511 inTmp.push_back(pITArg);
515 vectNbResult.push_back(getResultSize());
519 catch (const InternalError& ie)
522 types::typed_list outTmp;
523 cleanIn(inTmp, outTmp);
524 CoverageInstance::stopChrono((void*)&e);
528 } /* namespace ast */