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