Typo fixes
[scilab.git] / scilab / modules / ast / src / cpp / ast / debuggervisitor.cpp
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 "debuggervisitor.hxx"
17 #include "debugmanager.hxx"
18 #include "printvisitor.hxx"
19 #include "execvisitor.hxx"
20 #include "threadId.hxx"
21
22 extern "C"
23 {
24 #include "filemanager_interface.h"
25 }
26
27 namespace ast
28 {
29 void DebuggerVisitor::visit(const SeqExp  &e)
30 {
31     RunVisitor* exec = NULL;
32     std::list<Exp *>::const_iterator itExp;
33     debugger::DebuggerMagager* manager = debugger::DebuggerMagager::getInstance();
34
35     if (ConfigVariable::getEnableDebug() == false)
36     {
37         //enable debugger for next execution
38         ConfigVariable::setEnableDebug(true);
39
40         ExecVisitor exec;
41         e.accept(exec);
42         return;
43     }
44
45     for (const auto & exp : e.getExps())
46     {
47         if (e.isBreakable())
48         {
49             exp->resetBreak();
50             exp->setBreakable();
51         }
52
53         if (e.isContinuable())
54         {
55             exp->resetContinue();
56             exp->setContinuable();
57         }
58
59         if (e.isReturnable())
60         {
61             exp->setReturnable();
62         }
63
64         //debugger check !
65         if (ConfigVariable::getEnableDebug())
66         {
67             std::vector<ConfigVariable::WhereEntry> lWhereAmI = ConfigVariable::getWhere();
68             int iLine = (exp->getLocation().first_line - ConfigVariable::getMacroFirstLines()) + 1;
69
70             //manage step next
71             if (manager->isStepNext())
72             {
73                 manager->resetStepNext();
74                 manager->stop(exp, -1);
75             }
76             else if (manager->isStepIn())
77             {
78                 manager->resetStepIn();
79                 manager->stop(exp, -1);
80             }
81             else if (manager->isStepOut())
82             {
83                 manager->resetStepOut();
84                 manager->stop(exp, -1);
85             }
86             else
87             {
88                 //set information from debugger commands
89                 if (lWhereAmI.size() != 0 && manager->getBreakPointCount() != 0)
90                 {
91                     debugger::Breakpoints bps = manager->getAllBreakPoint();
92                     std::wstring functionName = lWhereAmI.back().m_name;
93                     int i = -1;
94                     for (const auto & bp : bps)
95                     {
96                         ++i;
97                         if (bp->isEnable() == false)
98                         {
99                             continue;
100                         }
101
102                         if (functionName == bp->getFunctioName())
103                         {
104                             if (bp->getMacroLine() == -1)
105                             {
106                                 //first pass in macro.
107                                 //update first line with real value
108                                 bp->setMacroLine(iLine);
109                             }
110
111                             if (bp->getMacroLine() == iLine)
112                             {
113                                 //check condition
114                                 if (bp->getConditionExp() != NULL)
115                                 {
116                                     //do not use debuggervisitor !
117                                     symbol::Context* pCtx = symbol::Context::getInstance();
118                                     try
119                                     {
120                                         ExecVisitor execCond;
121                                         //protect current env during condition execution
122                                         pCtx->scope_begin();
123                                         bp->getConditionExp()->accept(execCond);
124                                         types::InternalType* pIT = pCtx->getCurrentLevel(symbol::Symbol(L"ans"));
125                                         if (pIT == NULL ||
126                                                 pIT->isBool() == false ||
127                                                 ((types::Bool*)pIT)->isScalar() == false ||
128                                                 ((types::Bool*)pIT)->get(0) == 0)
129                                         {
130                                             pCtx->scope_end();
131                                             //not a boolean, not scalar or false
132                                             continue;
133                                         }
134
135                                         pCtx->scope_end();
136                                         //ok condition is valid and true
137                                     }
138                                     catch (ast::ScilabException &/*e*/)
139                                     {
140                                         pCtx->scope_end();
141                                         //not work !
142                                         //invalid breakpoint
143                                         continue;
144                                     }
145                                 }
146
147                                 //we have a breakpoint !
148                                 //stop execution and wait signal from debugger to restart
149                                 manager->stop(exp, i);
150
151                                 //only one breakpoint can be "call" on same exp
152                                 break;
153                             }
154                         }
155                     }
156                 }
157             }
158             exec = this;
159         }
160         else
161         {
162             //change visitor to execvitor instead of debuggervisitor
163             exec = new ExecVisitor();
164         }
165
166         //copy from runvisitor::seqexp
167         try
168         {
169             //reset default values
170             setResult(NULL);
171             int iExpectedSize = getExpectedSize();
172             setExpectedSize(-1);
173             exp->accept(*exec);
174             setExpectedSize(iExpectedSize);
175             types::InternalType * pIT = getResult();
176
177             // In case of exec file, set the file name in the Macro to store where it is defined.
178             int iFileID = ConfigVariable::getExecutedFileID();
179             if (iFileID && exp->isFunctionDec())
180             {
181                 types::InternalType* pITMacro = symbol::Context::getInstance()->get(exp->getAs<ast::FunctionDec>()->getSymbol());
182                 if (pITMacro)
183                 {
184                     types::Macro* pMacro = pITMacro->getAs<types::Macro>();
185                     const wchar_t* filename = getfile_filename(iFileID);
186                     // scilab.quit is not open with mopen
187                     // in this case filename is NULL because FileManager have not been filled.
188                     if (filename)
189                     {
190                         pMacro->setFileName(filename);
191                     }
192                 }
193             }
194
195             if (pIT != NULL)
196             {
197                 bool bImplicitCall = false;
198                 if (pIT->isCallable()) //to manage call without ()
199                 {
200                     types::Callable *pCall = pIT->getAs<types::Callable>();
201                     types::typed_list out;
202                     types::typed_list in;
203                     types::optional_list opt;
204
205                     try
206                     {
207                         //in this case of calling, we can return only one value
208                         int iSaveExpectedSize = getExpectedSize();
209                         setExpectedSize(1);
210
211                         pCall->invoke(in, opt, getExpectedSize(), out, e);
212                         setExpectedSize(iSaveExpectedSize);
213
214                         if (out.size() == 0)
215                         {
216                             setResult(NULL);
217                         }
218                         else
219                         {
220                             setResult(out[0]);
221                         }
222
223                         bImplicitCall = true;
224                     }
225                     catch (const InternalError& ie)
226                     {
227                         if (ConfigVariable::getLastErrorFunction() == L"")
228                         {
229                             ConfigVariable::setLastErrorFunction(pCall->getName());
230                             ConfigVariable::setLastErrorLine(e.getLocation().first_line);
231                         }
232
233                         throw ie;
234                     }
235                 }
236
237                 //don't output Simplevar and empty result
238                 if (getResult() != NULL && (!exp->isSimpleVar() || bImplicitCall))
239                 {
240                     //symbol::Context::getInstance()->put(symbol::Symbol(L"ans"), *execMe.getResult());
241                     types::InternalType* pITAns = getResult();
242                     symbol::Context::getInstance()->put(m_pAns, pITAns);
243                     if (exp->isVerbose() && ConfigVariable::isPrintOutput())
244                     {
245                         //TODO manage multiple returns
246                         scilabWriteW(L" ans  =\n\n");
247                         std::wostringstream ostrName;
248                         ostrName << L"ans";
249                         types::VariableToString(pITAns, ostrName.str().c_str());
250                     }
251                 }
252
253                 pIT->killMe();
254             }
255
256             if ((&e)->isBreakable() && exp->isBreak())
257             {
258                 const_cast<SeqExp *>(&e)->setBreak();
259                 exp->resetBreak();
260                 break;
261             }
262
263             if ((&e)->isContinuable() && exp->isContinue())
264             {
265                 const_cast<SeqExp *>(&e)->setContinue();
266                 exp->resetContinue();
267                 break;
268             }
269
270             if ((&e)->isReturnable() && exp->isReturn())
271             {
272                 const_cast<SeqExp *>(&e)->setReturn();
273                 exp->resetReturn();
274                 break;
275             }
276         }
277         catch (const InternalError& ie)
278         {
279             ConfigVariable::fillWhereError(ie.GetErrorLocation().first_line);
280
281             std::vector<ConfigVariable::WhereEntry> lWhereAmI = ConfigVariable::getWhere();
282
283             //where can be empty on last stepout, on first calling expression
284             if (lWhereAmI.size())
285             {
286                 std::wstring& filename = lWhereAmI.back().m_file_name;
287
288                 if (filename.empty())
289                 {
290                     //error in a console script
291                     std::wstring functionName = lWhereAmI.back().m_name;
292                     manager->errorInScript(functionName, exp);
293                 }
294                 else
295                 {
296                     manager->errorInFile(filename, exp);
297                 }
298             }
299
300             throw ie;
301         }
302
303         // If something other than NULL is given to setResult, then that would imply
304         // to make a cleanup in visit(ForExp) for example (e.getBody().accept(*this);)
305         setResult(NULL);
306
307     }
308
309     //propagate StepNext to parent SeqExp
310     if (ConfigVariable::getEnableDebug())
311     {
312     }
313 }
314 }
315