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