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