Analysis: infer when a refcount is required and add colors in DebugVisitor
[scilab.git] / scilab / modules / ast / src / cpp / ast / debugvisitor.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2008-2008 - DIGITEO - Bruno JOFRET
4  *  Copyright (C) 2015 - Scilab Enterprises - Calixte DENIZET
5  *
6  *  This file must be used under the terms of the CeCILL.
7  *  This source file is licensed as described in the file COPYING, which
8  *  you should have received as part of this distribution.  The terms
9  *  are also available at
10  *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
11  *
12  */
13
14 #include "debugvisitor.hxx"
15
16
17 namespace ast
18 {
19 static int level = -1;
20
21 #ifndef _MSC_VER
22 const std::wstring DebugVisitor::NORMAL = L"\033[0m";
23 const std::wstring DebugVisitor::BOLD = L"\033[1m";
24 const std::wstring DebugVisitor::RED = L"\033[31m";
25 const std::wstring DebugVisitor::GREEN = L"\033[32m";
26 const std::wstring DebugVisitor::YELLOW = L"\033[33m";
27 const std::wstring DebugVisitor::BLUE = L"\033[34m";
28 const std::wstring DebugVisitor::MAGENTA = L"\033[35m";
29 const std::wstring DebugVisitor::CYAN = L"\033[36m";
30 const std::wstring DebugVisitor::WHITE = L"\033[37m";
31 #else
32 const std::wstring DebugVisitor::NORMAL = L"";
33 const std::wstring DebugVisitor::BOLD = L"";
34 const std::wstring DebugVisitor::RED = L"";
35 const std::wstring DebugVisitor::GREEN = L"";
36 const std::wstring DebugVisitor::YELLOW = L"";
37 const std::wstring DebugVisitor::BLUE = L"";
38 const std::wstring DebugVisitor::MAGENTA = L"";
39 const std::wstring DebugVisitor::CYAN = L"";
40 const std::wstring DebugVisitor::WHITE = L"";
41 #endif
42
43 void DebugVisitor::START_NODE(const ast::Ast & e)
44 {
45     *ostr << L"(" << e.getNodeNumber() << L") ";
46     ++level;
47 }
48
49 void DebugVisitor::END_NODE(void)
50 {
51     --level;
52 }
53
54 void DebugVisitor::print(const std::wstring & str)
55 {
56     for (int i = 0 ; i < level; ++i)
57     {
58         *ostr << L"  ";
59     }
60     if (level > 0)
61     {
62         *ostr << L"     ";
63     }
64     *ostr << str << std::endl;
65 }
66
67 void DebugVisitor::print(const Location & loc)
68 {
69     if (colored)
70     {
71         *ostr << L"@(" << YELLOW << loc.first_line << L"." << BOLD << loc.first_column << NORMAL << L" -> "
72               << YELLOW << loc.last_line << L"." << BOLD << loc.last_column << NORMAL << L")";
73     }
74     else
75     {
76         *ostr << L"@(" << loc.first_line << L"." << loc.first_column << L" -> "
77               << loc.last_line << L"." << loc.last_column << L")";
78     }
79 }
80
81 void DebugVisitor::print(const std::wstring & pre, const Location & loc, const std::wstring & post, const std::wstring & deco)
82 {
83     for (int i = 0 ; i < level; ++i)
84     {
85         *ostr << L"  ";
86     }
87     if (level > 0)
88     {
89         *ostr << L"|_./ ";
90     }
91
92     *ostr << pre << L' ';
93     print(loc);
94
95     if (!post.empty())
96     {
97         *ostr << L" : " << post;
98     }
99     if (!deco.empty())
100     {
101         *ostr << L' ' << deco;
102     }
103     *ostr << std::endl;
104 }
105
106 void DebugVisitor::print(const std::wstring & str, const Exp & e)
107 {
108     std::wstring expType;
109     if (colored)
110     {
111         expType = BOLD + e.getTypeString() + NORMAL;
112     }
113     else
114     {
115         expType = e.getTypeString();
116     }
117
118     if (printDecoration)
119     {
120         std::wostringstream wos;
121         wos << L"Deco(" << e.getDecorator() << L")";
122         print(expType, e.getLocation(), str, wos.str());
123     }
124     else
125     {
126         print(expType, e.getLocation(), str, L"");
127     }
128 }
129
130 void DebugVisitor::print(const Exp & e)
131 {
132     print(L"", e);
133 }
134
135 void DebugVisitor::visit(const MatrixExp & e)
136 {
137     START_NODE(e);
138     print(e);
139     exps_t lines = e.getLines();
140     for (exps_t::const_iterator it = lines.begin(), itEnd = lines.end(); it != itEnd ; ++it)
141     {
142         (*it)->accept(*this);
143     }
144     END_NODE();
145 }
146
147 void DebugVisitor::visit(const MatrixLineExp & e)
148 {
149     START_NODE(e);
150     print(e);
151     exps_t columns = e.getColumns();
152     for (exps_t::const_iterator it = columns.begin(), itEnd = columns.end(); it != itEnd ; ++it)
153     {
154         (*it)->accept(*this);
155     }
156     END_NODE();
157 }
158
159 void DebugVisitor::visit(const CellExp & e)
160 {
161     START_NODE(e);
162     print(e);
163     exps_t lines = e.getLines();
164     for (exps_t::const_iterator it = lines.begin(), itEnd = lines.end(); it != itEnd ; ++it)
165     {
166         (*it)->accept(*this);
167     }
168     END_NODE();
169 }
170
171 void DebugVisitor::visit(const StringExp & e)
172 {
173     START_NODE(e);
174     std::wostringstream stream;
175     if (e.getConstant())
176     {
177         printInternalType<types::String>(stream, e.getConstant());
178     }
179     else
180     {
181         stream << e.getValue();
182     }
183     if (colored)
184     {
185         print(RED + stream.str() + NORMAL, e);
186     }
187     else
188     {
189         print(stream.str(), e);
190     }
191     END_NODE();
192 }
193
194 void DebugVisitor::visit(const CommentExp & e)
195 {
196     START_NODE(e);
197     if (colored)
198     {
199         print(GREEN + e.getComment() + NORMAL, e);
200     }
201     else
202     {
203         print(e.getComment(), e);
204     }
205     END_NODE();
206 }
207
208 void DebugVisitor::visit(const DoubleExp & e)
209 {
210     START_NODE(e);
211     std::wostringstream stream;
212     types::InternalType * pIT = e.getConstant();
213     if (pIT)
214     {
215         if (pIT->isImplicitList())
216         {
217             types::ImplicitList * pIL = static_cast<types::ImplicitList *>(pIT);
218             stream << static_cast<types::Double *>(pIL->getStart())->get(0) << L":"
219                    << static_cast<types::Double *>(pIL->getStep())->get(0) << L":"
220                    << static_cast<types::Double *>(pIL->getEnd())->get(0);
221         }
222         else
223         {
224             printInternalType<types::Double>(stream, pIT);
225         }
226     }
227     else
228     {
229         stream << e.getValue();
230     }
231     if (colored)
232     {
233         print(RED + stream.str() + NORMAL, e);
234     }
235     else
236     {
237         print(stream.str(), e);
238     }
239     END_NODE();
240 }
241
242 void DebugVisitor::visit(const BoolExp & e)
243 {
244     START_NODE(e);
245     std::wostringstream stream;
246     if (e.getConstant())
247     {
248         printInternalType<types::Bool>(stream, e.getConstant());
249     }
250     else
251     {
252         stream << e.getValue();
253     }
254     if (colored)
255     {
256         print(RED + stream.str() + NORMAL, e);
257     }
258     else
259     {
260         print(stream.str(), e);
261     }
262     END_NODE();
263 }
264
265 void DebugVisitor::visit(const NilExp & e)
266 {
267     START_NODE(e);
268     print(e);
269     END_NODE();
270 }
271
272 void DebugVisitor::visit(const SimpleVar & e)
273 {
274     START_NODE(e);
275     std::wstring str;
276     if (colored)
277     {
278         str = RED + e.getSymbol().getName() + NORMAL;
279     }
280     else
281     {
282         str = e.getSymbol().getName();
283     }
284     if (printDecoration)
285     {
286         std::wstring ty;
287         analysis::TIType type = e.getDecorator().getResult().getType();
288         if (type.type != analysis::TIType::UNKNOWN)
289         {
290             if (type.isscalar())
291             {
292                 ty = L" (" + analysis::TIType::toString(type.type) + L")";
293             }
294             else
295             {
296                 ty = L" (" + analysis::TIType::toString(type.type) + L"*)";
297             }
298         }
299         str += ty;
300     }
301     print(str, e);
302
303     END_NODE();
304 }
305
306 void DebugVisitor::visit(const ColonVar & e)
307 {
308     START_NODE(e);
309     print(e);
310     END_NODE();
311 }
312
313 void DebugVisitor::visit(const DollarVar & e)
314 {
315     START_NODE(e);
316     print(e);
317     END_NODE();
318 }
319
320 void DebugVisitor::visit(const ArrayListVar & e)
321 {
322     START_NODE(e);
323     print(e);
324     exps_t vars = e.getVars();
325     for (exps_t::const_iterator it = vars.begin (), itEnd = vars.end(); it != itEnd; ++it)
326     {
327         (*it)->accept(*this);
328     }
329     END_NODE();
330 }
331
332 void DebugVisitor::visit(const FieldExp & e)
333 {
334     START_NODE(e);
335     print(e);
336     e.getHead()->accept(*this);
337     e.getTail()->accept(*this);
338     END_NODE();
339 }
340
341 void DebugVisitor::visit(const OpExp & e)
342 {
343     START_NODE(e);
344     print(e);
345     e.getLeft().accept(*this);
346     e.getRight().accept(*this);
347     END_NODE();
348 }
349
350 void DebugVisitor::visit(const LogicalOpExp & e)
351 {
352     START_NODE(e);
353     print(e);
354     e.getLeft().accept(*this);
355     e.getRight().accept(*this);
356     END_NODE();
357 }
358
359 void DebugVisitor::visit(const AssignExp & e)
360 {
361     START_NODE(e);
362     print(e);
363     e.getLeftExp().accept(*this);
364     e.getRightExp().accept(*this);
365     END_NODE();
366 }
367
368 void DebugVisitor::visit(const CellCallExp & e)
369 {
370     START_NODE(e);
371     print(e);
372     e.getName().accept(*this);
373
374     exps_t args = e.getArgs();
375     for (auto arg : args)
376     {
377         arg->accept(*this);
378     }
379
380     END_NODE();
381 }
382
383 void DebugVisitor::visit(const CallExp & e)
384 {
385     START_NODE(e);
386     print(e);
387     e.getName().accept(*this);
388
389     exps_t args = e.getArgs();
390     for (auto arg : args)
391     {
392         arg->accept(*this);
393     }
394
395     END_NODE();
396 }
397
398 void DebugVisitor::visit(const IfExp & e)
399 {
400     START_NODE(e);
401     print(e);
402     e.getTest().accept(*this);
403     e.getThen().accept(*this);
404     if (e.hasElse())
405     {
406         e.getElse ().accept(*this);
407     }
408     END_NODE();
409 }
410
411 void DebugVisitor::visit(const TryCatchExp & e)
412 {
413     START_NODE(e);
414     print(e);
415     e.getTry().accept(*this);
416     e.getCatch().accept(*this);
417     END_NODE();
418 }
419
420 void DebugVisitor::visit(const WhileExp & e)
421 {
422     START_NODE(e);
423     print(e);
424     e.getTest().accept(*this);
425     e.getBody().accept(*this);
426     END_NODE();
427 }
428
429 void DebugVisitor::visit(const ForExp & e)
430 {
431     START_NODE(e);
432     print(e);
433     e.getVardec().accept(*this);
434     e.getBody().accept(*this);
435     END_NODE();
436 }
437
438 void DebugVisitor::visit(const ContinueExp & e)
439 {
440     START_NODE(e);
441     print(e);
442     END_NODE();
443 }
444
445 void DebugVisitor::visit(const BreakExp & e)
446 {
447     START_NODE(e);
448     print(e);
449     END_NODE();
450 }
451
452 void DebugVisitor::visit(const ReturnExp & e)
453 {
454     START_NODE(e);
455     print(e);
456     if (!e.isGlobal())
457     {
458         e.getExp().accept(*this);
459     }
460     END_NODE();
461 }
462
463 void DebugVisitor::visit(const SelectExp & e)
464 {
465     START_NODE(e);
466     print(e);
467     e.getSelect()->accept(*this);
468
469     exps_t cases = e.getCases();
470     for (auto exp : cases)
471     {
472         exp->accept(*this);
473     }
474
475     if (e.getDefaultCase() != NULL)
476     {
477         e.getDefaultCase()->accept(*this);
478     }
479     END_NODE();
480 }
481
482 void DebugVisitor::visit(const CaseExp & e)
483 {
484     START_NODE(e);
485     print(e);
486     e.getTest()->accept(*this);
487     e.getBody()->accept(*this);
488     END_NODE();
489 }
490
491 void DebugVisitor::visit(const SeqExp & e)
492 {
493     START_NODE(e);
494     print(e);
495     for (exps_t::const_iterator it = e.getExps().begin (), itEnd = e.getExps().end(); it != itEnd; ++it)
496     {
497         (*it)->accept(*this);
498     }
499     END_NODE();
500 }
501
502 void DebugVisitor::visit(const ArrayListExp & e)
503 {
504     START_NODE(e);
505     print(e);
506     for (exps_t::const_iterator it = e.getExps().begin (), itEnd = e.getExps().end(); it != itEnd; ++it)
507     {
508         (*it)->accept(*this);
509     }
510     END_NODE();
511 }
512
513 void DebugVisitor::visit(const AssignListExp & e)
514 {
515     START_NODE(e);
516     print(e);
517     for (exps_t::const_iterator it = e.getExps().begin (), itEnd = e.getExps().end(); it != itEnd; ++it)
518     {
519         (*it)->accept(*this);
520     }
521     END_NODE();
522 }
523
524 void DebugVisitor::visit(const NotExp & e)
525 {
526     START_NODE(e);
527     print(e);
528     e.getExp().accept(*this);
529     END_NODE();
530 }
531
532 void DebugVisitor::visit(const TransposeExp & e)
533 {
534     START_NODE(e);
535     print(e);
536     e.getExp().accept(*this);
537     END_NODE();
538 }
539
540 void DebugVisitor::visit(const VarDec & e)
541 {
542     std::wstring sym, name;
543     if (colored)
544     {
545         sym = BOLD + L"Symbol" + NORMAL;
546         name = RED + e.getSymbol().getName() + NORMAL;
547     }
548     else
549     {
550         sym = L"Symbol";
551         name = e.getSymbol().getName();
552     }
553
554     START_NODE(e);
555     print(e);
556     START_NODE(e);
557     print(sym, e.getLocation(), name, L"");
558     END_NODE();
559     e.getInit().accept(*this);
560     END_NODE();
561 }
562
563 void DebugVisitor::visit(const FunctionDec & e)
564 {
565     START_NODE(e);
566     print(e);
567     // FIXME
568
569     // First ask if there are some return values.
570     //visit(e.returns_get());
571
572     // Then get the function name
573     //visit(e.getName());
574
575     // Then get function args
576     //visit(e.args_get());
577
578     // Now debug function body
579     e.getBody().accept(*this);
580
581     END_NODE();
582 }
583
584 void DebugVisitor::visit(const ListExp &e)
585 {
586     START_NODE(e);
587     print(e);
588     e.getStart().accept(*this);
589     e.getStep().accept(*this);
590     e.getEnd().accept(*this);
591     END_NODE();
592 }
593
594 void DebugVisitor::visit(const OptimizedExp &e)
595 {
596     e.getOriginal()->accept(*this);
597 }
598
599 void DebugVisitor::visit(const MemfillExp &e)
600 {
601     START_NODE(e);
602     print(e);
603     e.getValue().accept(*this);
604
605     exps_t args = e.getArgs();
606     for (auto arg : args)
607     {
608         arg->accept(*this);
609     }
610
611     END_NODE();
612 }
613
614 void DebugVisitor::visit(const DAXPYExp &e)
615 {
616     START_NODE(e);
617     print(e);
618     e.getA().accept(*this);
619     e.getX().accept(*this);
620     e.getY().accept(*this);
621     END_NODE();
622
623     //e.getOriginal()->accept(*this);
624 }
625
626 void DebugVisitor::visit(const IntSelectExp & e)
627 {
628     e.getOriginal()->accept(*this);
629 }
630
631 void DebugVisitor::visit(const StringSelectExp & e)
632 {
633     e.getOriginal()->accept(*this);
634 }
635
636 }