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