03dade1a9a680797f83ab843488048c73642022e
[scilab.git] / scilab / modules / ast / src / cpp / ast / run_SeqExp.hpp
1 /*
2 *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 *  Copyright (C) 2015 - Scilab Enterprises - Antoine ELIAS
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 #include <fstream>
17
18 //file included in runvisitor.cpp
19 namespace ast {
20
21 template <class T>
22 void RunVisitorT<T>::visitprivate(const SeqExp  &e)
23 {
24     CoverageInstance::invokeAndStartChrono((void*)&e);
25     int lastLine = 0;
26     ast::exps_t exps = e.getExps();
27     ast::exps_t::const_iterator it = exps.begin();
28     ast::exps_t::const_iterator itEnd = exps.end();
29
30
31     /*stuff of printf input during execution*/
32     std::string str;
33     int iCurrentLine = -1; //no data in str
34
35     std::ifstream* file = nullptr;
36     if (e.getExecFrom() == SeqExp::EXEC)
37     {
38         //open input file to print exp from it
39         std::wstring strFile = ConfigVariable::getExecutedFile();
40         if (strFile != L"")
41         {
42             char* cfilename = wide_string_to_UTF8(strFile.data());
43             file = new std::ifstream(cfilename);
44             FREE(cfilename);
45         }
46     }
47
48     if (exps.size() == 0)
49     {
50         if (ConfigVariable::isExecutionBreak())
51         {
52             ConfigVariable::resetExecutionBreak();
53             if (ConfigVariable::isPrintInteractive())
54             {
55                 ClearTemporaryPrompt();
56             }
57
58             StorePrioritaryCommand("pause");
59             ThreadManagement::WaitForRunMeSignal();
60         }
61
62         // interrupt me to execute a prioritary command
63         while (StaticRunner_isRunnerAvailable() == 1 && StaticRunner_isInterruptibleCommand() == 1)
64         {
65             StaticRunner_launch();
66         }
67
68         if (file)
69         {
70             file->close();
71             delete file;
72         }
73
74         CoverageInstance::stopChrono((void*)&e);
75         return;
76     }
77
78     for (; it != itEnd; ++it)
79     {
80         if (ConfigVariable::isExecutionBreak())
81         {
82             ConfigVariable::resetExecutionBreak();
83             if (ConfigVariable::isPrintInteractive())
84             {
85                 ClearTemporaryPrompt();
86             }
87
88             StorePrioritaryCommand("pause");
89             ThreadManagement::WaitForRunMeSignal();
90         }
91
92         // interrupt me to execute a prioritary command
93         while (StaticRunner_isRunnerAvailable() == 1 && StaticRunner_isInterruptibleCommand() == 1)
94         {
95             StaticRunner_launch();
96         }
97
98         //printf input expression line following mode configuration
99         if (file && ConfigVariable::isPrintInput())
100         {
101             Location loc = (*it)->getLocation();
102             if (iCurrentLine + 1 < loc.first_line)
103             {
104                 //get prompt
105                 std::string stPrompt = GetCurrentPrompt();
106                 if (ConfigVariable::isPrintInteractive())
107                 {
108                     stPrompt = SCIPROMPT_PAUSE;
109                 }
110
111                 ast::exps_t::const_iterator k = it;
112                 int iLastLine = loc.last_line;
113                 int iCurrentCol = 0; //no data in str
114                 do
115                 {
116                     str = printExp(*file, *k, stPrompt, &iCurrentLine, &iCurrentCol, str);
117                     iLastLine = (*k)->getLocation().last_line;
118                     k++;
119                 } while (k != exps.end() && (*k)->getLocation().first_line == iLastLine);
120             }
121         }
122
123         if ((*it)->isCommentExp())
124         {
125             continue;
126         }
127
128         try
129         {
130             //reset default values
131             setResult(NULL);
132             int iExpectedSize = getExpectedSize();
133             setExpectedSize(-1);
134             (*it)->accept(*this);
135             setExpectedSize(iExpectedSize);
136             types::InternalType * pIT = getResult();
137
138             if((*it)->isFunctionDec())
139             {
140                 // In case of exec file, set the file name in the Macro to store where it is defined.
141                 std::wstring strFile = ConfigVariable::getExecutedFile();
142                 const std::vector<ConfigVariable::WhereEntry>& lWhereAmI = ConfigVariable::getWhere();
143
144                 if (strFile != L"" &&  // check if we are executing a script or a macro
145                     lWhereAmI.empty() == false &&
146                     lWhereAmI.back().m_file_name != nullptr && // check the last function execution is a macro
147                     *(lWhereAmI.back().m_file_name) == strFile) // check the last execution is the same macro as the executed one
148                 {
149                     types::InternalType* pITMacro = symbol::Context::getInstance()->get((*it)->getAs<FunctionDec>()->getSymbol());
150                     if (pITMacro)
151                     {
152                         types::Macro* pMacro = pITMacro->getAs<types::Macro>();
153                         pMacro->setFileName(strFile);
154                     }
155                 }
156             }
157
158             if (pIT != NULL)
159             {
160                 bool bImplicitCall = false;
161                 if (pIT->isCallable()) //to manage call without ()
162                 {
163                     types::Callable *pCall = pIT->getAs<types::Callable>();
164                     types::typed_list out;
165                     types::typed_list in;
166                     types::optional_list opt;
167
168                     try
169                     {
170                         //in this case of calling, we can return at most one value
171                         int iSaveExpectedSize = getExpectedSize();
172                         setExpectedSize(0);
173
174                         pCall->invoke(in, opt, getExpectedSize(), out, **it);
175                         setExpectedSize(iSaveExpectedSize);
176
177                         if (out.size() == 0)
178                         {
179                             setResult(NULL);
180                         }
181                         else
182                         {
183                             setResult(out[0]);
184                         }
185
186                         bImplicitCall = true;
187                     }
188                     catch (const InternalError& ie)
189                     {
190                         if (ConfigVariable::getLastErrorFunction() == L"")
191                         {
192                             ConfigVariable::setLastErrorFunction(pCall->getName());
193                             ConfigVariable::setLastErrorLine(e.getLocation().first_line);
194                         }
195                         CoverageInstance::stopChrono((void*)&e);
196                         throw ie;
197                     }
198                 }
199                 else if (pIT->isImplicitList())
200                 {
201                     //expand implicit when possible
202                     types::ImplicitList* pIL = pIT->getAs<types::ImplicitList>();
203                     if (pIL->isComputable())
204                     {
205                         types::InternalType* p = pIL->extractFullMatrix();
206                         if (p)
207                         {
208                             setResult(p);
209                         }
210                     }
211                 }
212
213                 //don't output Simplevar and empty result
214                 if (getResult() != NULL && (!(*it)->isSimpleVar() || bImplicitCall))
215                 {
216                     //symbol::Context::getInstance()->put(symbol::Symbol(L"ans"), *execMe.getResult());
217                     types::InternalType* pITAns = getResult();
218                     symbol::Context::getInstance()->put(m_pAns, pITAns);
219                     if ((*it)->isVerbose() && ConfigVariable::isPrintOutput())
220                     {
221                         //TODO manage multiple returns
222                         scilabWriteW(L" ans  =\n");
223                         if (ConfigVariable::isPrintCompact() == false)
224                         {
225                             scilabWriteW(L"\n");
226                         }
227                         std::wostringstream ostrName;
228                         ostrName << L"ans";
229                         VariableToString(pITAns, ostrName.str().c_str());
230                     }
231                 }
232
233                 pIT->killMe();
234             }
235
236             if (ConfigVariable::isPrintInteractive())
237             {
238                 Location loc = (*it)->getLocation();
239                 if (lastLine < loc.first_line)
240                 {
241                     //break execution
242                     SetTemporaryPrompt(SCIPROMPT_PAUSE);
243
244                     // The console thread must not parse the next console input.
245                     ConfigVariable::setScilabCommand(0);
246
247                     // Get the console input filled by the console thread.
248                     char* pcConsoleReadStr = ConfigVariable::getConsoleReadStr();
249                     ThreadManagement::SendConsoleExecDoneSignal();
250                     while (pcConsoleReadStr == NULL)
251                     {
252                         pcConsoleReadStr = ConfigVariable::getConsoleReadStr();
253                         ThreadManagement::SendConsoleExecDoneSignal();
254                     }
255
256                     // reset flag to default value
257                     ConfigVariable::setScilabCommand(1);
258
259                     if (pcConsoleReadStr && pcConsoleReadStr[0] == 'p' && pcConsoleReadStr[1] == '\0')
260                     {
261                         //mode pause
262                         ConfigVariable::setExecutionBreak();
263                     }
264                 }
265
266                 lastLine = loc.last_line;
267             }
268
269             if ((&e)->isBreakable() && (*it)->isBreak())
270             {
271                 const_cast<SeqExp *>(&e)->setBreak();
272                 (*it)->resetBreak();
273                 break;
274             }
275
276             if ((&e)->isContinuable() && (*it)->isContinue())
277             {
278                 const_cast<SeqExp *>(&e)->setContinue();
279                 (*it)->resetContinue();
280                 break;
281             }
282
283             if ((&e)->isReturnable() && (*it)->isReturn())
284             {
285                 const_cast<SeqExp *>(&e)->setReturn();
286                 (*it)->resetReturn();
287                 break;
288             }
289         }
290         catch (const InternalError& ie)
291         {
292             ConfigVariable::fillWhereError(ie.GetErrorLocation().first_line);
293             CoverageInstance::stopChrono((void*)&e);
294             if (file)
295             {
296                 file->close();
297                 delete file;
298             }
299
300             throw ie;
301         }
302         catch (const InternalAbort& ia)
303         {
304             if (file)
305             {
306                 file->close();
307                 delete file;
308             }
309             throw ia;
310         }
311         // If something other than NULL is given to setResult, then that would imply
312         // to make a cleanup in visit(ForExp) for example (e.getBody().accept(*this);)
313         setResult(NULL);
314     }
315
316     if (file)
317     {
318         file->close();
319         delete file;
320     }
321     CoverageInstance::stopChrono((void*)&e);
322 }
323
324
325 } /* namespace ast */