Merge remote-tracking branch 'origin/master' into windows
[scilab.git] / scilab / modules / coverage / src / cpp / CodePrinterVisitor.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2015 - Scilab Enterprises - Calixte DENIZET
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 "CodePrinterVisitor.hxx"
17
18 namespace coverage
19 {
20
21 void CodePrinterVisitor::visit(const ast::MatrixExp & e)
22 {
23     printer.handleExpStart(&e);
24     printer.handleOpenClose(SCI_OPEN_MATRIX);
25
26     const bool mustReturn = e.getLocation().first_line != e.getLocation().last_line;
27     const int shift = mustReturn ? (int)(printer.getLineCharCount() - printer.getIndentSize()) : 0;
28     const ast::exps_t & lines = e.getLines();
29     if (lines.size())
30     {
31         ast::exps_t::const_iterator last_line = std::prev(lines.end());
32         for (ast::exps_t::const_iterator i = lines.begin(), er = lines.end(); i != er; ++i)
33         {
34             const ast::exps_t & columns = static_cast<ast::MatrixLineExp *>(*i)->getColumns();
35             if (columns.size())
36             {
37                 ast::exps_t::const_iterator last_column = std::prev(columns.end());
38                 for (ast::exps_t::const_iterator j = columns.begin(), ec = columns.end(); j != ec; ++j)
39                 {
40                     (*j)->accept(*this);
41                     if (j != last_column)
42                     {
43                         printer.handleDefault(SCI_COMMA);
44                     }
45                 }
46
47                 if (i != last_line)
48                 {
49                     printer.handleDefault(SCI_SEMICOLON);
50                     if (mustReturn)
51                     {
52                         printer.handleNewLine();
53                         printer.handleExpStart(&e);
54                         if (shift > 0)
55                         {
56                             printer.handleNothing(std::string(shift, L' '));
57                         }
58                     }
59                 }
60             }
61         }
62     }
63     printer.handleOpenClose(SCI_CLOSE_MATRIX);
64     printer.handleExpEnd(&e);
65 }
66
67 void CodePrinterVisitor::visit(const ast::MatrixLineExp & e)
68 {
69
70 }
71
72 void CodePrinterVisitor::visit(const ast::CellExp & e)
73 {
74     printer.handleExpStart(&e);
75     printer.handleOpenClose(SCI_OPEN_CELL);
76
77     const bool mustReturn = e.getLocation().first_line != e.getLocation().last_line;
78     const unsigned int shift = mustReturn ? (unsigned int)(printer.getLineCharCount() - printer.getIndentSize()) : 0;
79     const ast::exps_t & lines = e.getLines();
80     if (lines.size())
81     {
82         ast::exps_t::const_iterator last_line = std::prev(lines.end());
83         for (ast::exps_t::const_iterator i = lines.begin(), er = lines.end(); i != er; ++i)
84         {
85             const ast::exps_t & columns = static_cast<ast::MatrixLineExp *>(*i)->getColumns();
86             if (columns.size())
87             {
88                 ast::exps_t::const_iterator last_column = std::prev(columns.end());
89                 for (ast::exps_t::const_iterator j = columns.begin(), ec = columns.end(); j != ec; ++j)
90                 {
91                     (*j)->accept(*this);
92                     if (j != last_column)
93                     {
94                         printer.handleDefault(SCI_COMMA);
95                     }
96                 }
97
98                 if (i != last_line)
99                 {
100                     printer.handleDefault(SCI_SEMICOLON);
101                     if (mustReturn)
102                     {
103                         printer.handleNewLine();
104                         printer.handleNothing(std::string(shift, L' '));
105                     }
106                 }
107             }
108         }
109     }
110     printer.handleOpenClose(SCI_CLOSE_CELL);
111     printer.handleExpEnd(&e);
112 }
113
114 void CodePrinterVisitor::visit(const ast::StringExp & e)
115 {
116     printer.handleExpStart(&e);
117     printer.handleOpenClose(SCI_OPEN_STRING);
118     printer.handleString(e.getValue());
119     printer.handleOpenClose(SCI_CLOSE_STRING);
120     printer.handleExpEnd(&e);
121 }
122
123 void CodePrinterVisitor::visit(const ast::CommentExp & e)
124 {
125     printer.handleExpStart(&e);
126     printer.handleComment("// " + e.getComment());
127     printer.handleExpEnd(&e);
128 }
129
130 void CodePrinterVisitor::visit(const ast::DoubleExp & e)
131 {
132     printer.handleExpStart(&e);
133     const double x = e.getValue();
134     if (analysis::tools::isAnInt(x))
135     {
136         printer.handleNumber(x >= 0 ? std::to_string((uint64_t)x) : std::to_string((int64_t)x));
137     }
138     else
139     {
140         printer.handleNumber(std::to_string(e.getValue()));
141     }
142     printer.handleExpEnd(&e);
143 }
144
145 void CodePrinterVisitor::visit(const ast::BoolExp & e)
146 {
147     printer.handleExpStart(&e);
148     printer.handleConstants(e.getValue() ? SCI_TRUE : SCI_FALSE);
149     printer.handleExpEnd(&e);
150 }
151
152 void CodePrinterVisitor::visit(const ast::NilExp &/*e*/)
153 {
154     /* Do Nothing */
155 }
156
157 void CodePrinterVisitor::visit(const ast::SimpleVar & e)
158 {
159     printer.handleExpStart(&e);
160     const symbol::Symbol & sym = e.getSymbol();
161     types::InternalType * pIT = symbol::Context::getInstance()->get(sym);
162     if (pIT)
163     {
164         switch (pIT->getType())
165         {
166             case types::InternalType::ScilabFunction:
167                 printer.handleCommands(sym.getName());
168                 break;
169             case types::InternalType::ScilabMacro:
170                 printer.handleMacros(sym.getName());
171                 break;
172             case types::InternalType::ScilabMacroFile:
173                 printer.handleMacros(sym.getName());
174                 break;
175             default:
176             {
177                 const std::string & name = sym.getName();
178                 if (name == "%t" || name == "%T" || name == "%f" || name == "%F" || name == "%e" || name == "%pi" || name == "%inf" || name == "%i" || name == "%z" || name == "%s" || name == "%nan" || name == "%eps" || name == "SCI" || name == "WSCI" || name == "SCIHOME" || name == "TMPDIR")
179                 {
180                     printer.handleConstants(name);
181                 }
182                 else
183                 {
184                     printer.handleName(name);
185                 }
186                 break;
187             }
188         }
189     }
190     else
191     {
192         printer.handleName(sym.getName());
193     }
194     printer.handleExpEnd(&e);
195 }
196
197 void CodePrinterVisitor::visit(const ast::ColonVar & e)
198 {
199     printer.handleExpStart(&e);
200     printer.handleSpecial(SCI_COLON);
201     printer.handleExpEnd(&e);
202 }
203
204 void CodePrinterVisitor::visit(const ast::DollarVar & e)
205 {
206     printer.handleExpStart(&e);
207     printer.handleSpecial(SCI_DOLLAR);
208     printer.handleExpEnd(&e);
209 }
210
211 void CodePrinterVisitor::visit(const ast::ArrayListVar & e)
212 {
213     printer.handleExpStart(&e);
214     const ast::exps_t & vars = e.getVars();
215     if (vars.size())
216     {
217         ast::exps_t::const_iterator last = std::prev(vars.end());
218         for (ast::exps_t::const_iterator i = vars.begin(), e = vars.end(); i != e; ++i)
219         {
220             const symbol::Symbol & sym = static_cast<ast::SimpleVar *>(*i)->getSymbol();
221             printer.handleInOutArgsDec(sym.getName());
222             if (i != last)
223             {
224                 printer.handleDefault(SCI_COMMA);
225                 printer.handleNothing(" ");
226             }
227         }
228     }
229     printer.handleExpEnd(&e);
230 }
231
232 void CodePrinterVisitor::visit(const ast::FieldExp & e)
233 {
234     printer.handleExpStart(&e);
235     e.getHead()->accept(*this);
236     printer.handleOperator(SCI_FVAR_SEPARATOR);
237     e.getTail()->accept(*this);
238     printer.handleExpEnd(&e);
239 }
240
241 void CodePrinterVisitor::visit(const ast::OpExp & e)
242 {
243     printer.handleExpStart(&e);
244     if (e.getOper() != ast::OpExp::unaryMinus)
245     {
246         if (e.getLeft().isOpExp() || e.getLeft().isLogicalOpExp())
247         {
248             printer.handleOpenClose(SCI_LPAREN);
249             e.getLeft().accept(*this);
250             printer.handleOpenClose(SCI_RPAREN);
251         }
252         else
253         {
254             e.getLeft().accept(*this);
255         }
256         printer.handleNothing(" ");
257     }
258
259     switch (e.getOper())
260     {
261         case ast::OpExp::plus:
262             printer.handleOperator(SCI_PLUS);
263             break;
264         case ast::OpExp::unaryMinus:
265         case ast::OpExp::minus:
266             printer.handleOperator(SCI_MINUS);
267             break;
268         case ast::OpExp::times:
269             printer.handleOperator(SCI_TIMES);
270             break;
271         case ast::OpExp::rdivide:
272             printer.handleOperator(SCI_RDIVIDE);
273             break;
274         case ast::OpExp::ldivide:
275             printer.handleOperator(SCI_LDIVIDE);
276             break;
277         case ast::OpExp::power:
278             printer.handleOperator(SCI_POWER);
279             break;
280         case ast::OpExp::dottimes:
281             printer.handleOperator(SCI_DOTTIMES);
282             break;
283         case ast::OpExp::dotrdivide:
284             printer.handleOperator(SCI_DOTRDIVIDE);
285             break;
286         case ast::OpExp::dotldivide:
287             printer.handleOperator(SCI_DOTLDIVIDE);
288             break;
289         case ast::OpExp::dotpower:
290             printer.handleOperator(SCI_DOTPOWER);
291             break;
292         case ast::OpExp::krontimes:
293             printer.handleOperator(SCI_KRONTIMES);
294             break;
295         case ast::OpExp::kronrdivide:
296             printer.handleOperator(SCI_KRONRDIVIDE);
297             break;
298         case ast::OpExp::kronldivide:
299             printer.handleOperator(SCI_KRONLDIVIDE);
300             break;
301         case ast::OpExp::controltimes:
302             printer.handleOperator(SCI_CONTROLTIMES);
303             break;
304         case ast::OpExp::controlrdivide:
305             printer.handleOperator(SCI_CONTROLRDIVIDE);
306             break;
307         case ast::OpExp::controlldivide:
308             printer.handleOperator(SCI_CONTROLLDIVIDE);
309             break;
310         case ast::OpExp::eq:
311             printer.handleOperator(SCI_EQ);
312             break;
313         case ast::OpExp::ne:
314             printer.handleOperator(SCI_NE);
315             break;
316         case ast::OpExp::lt:
317             printer.handleOperator(SCI_LT);
318             break;
319         case ast::OpExp::le:
320             printer.handleOperator(SCI_LE);
321             break;
322         case ast::OpExp::gt:
323             printer.handleOperator(SCI_GT);
324             break;
325         case ast::OpExp::ge:
326             printer.handleOperator(SCI_GE);
327             break;
328         default :
329             break;
330     }
331
332     if (e.getOper() != ast::OpExp::unaryMinus)
333     {
334         printer.handleNothing(" ");
335     }
336
337     if (e.getRight().isOpExp() || e.getRight().isLogicalOpExp())
338     {
339         printer.handleOpenClose(SCI_LPAREN);
340         e.getRight().accept(*this);
341         printer.handleOpenClose(SCI_RPAREN);
342     }
343     else
344     {
345         e.getRight().accept(*this);
346     }
347     printer.handleExpEnd(&e);
348 }
349
350 void CodePrinterVisitor::visit(const ast::LogicalOpExp & e)
351 {
352     printer.handleExpStart(&e);
353     if (e.getLeft().isOpExp() || e.getLeft().isLogicalOpExp())
354     {
355         printer.handleOpenClose(SCI_LPAREN);
356         e.getLeft().accept(*this);
357         printer.handleOpenClose(SCI_RPAREN);
358     }
359     else
360     {
361         e.getLeft().accept(*this);
362     }
363     printer.handleNothing(" ");
364
365     switch (e.getOper())
366     {
367         case ast::LogicalOpExp::logicalAnd:
368             printer.handleOperator(SCI_AND);
369             break;
370         case ast::LogicalOpExp::logicalOr:
371             printer.handleOperator(SCI_OR);
372             break;
373         case ast::LogicalOpExp::logicalShortCutAnd:
374             printer.handleOperator(SCI_ANDAND);
375             break;
376         case ast::LogicalOpExp::logicalShortCutOr:
377             printer.handleOperator(SCI_OROR);
378             break;
379         default :
380             break;
381     }
382
383     printer.handleNothing(" ");
384     if (e.getRight().isOpExp() || e.getRight().isLogicalOpExp())
385     {
386         printer.handleOpenClose(SCI_LPAREN);
387         e.getRight().accept(*this);
388         printer.handleOpenClose(SCI_RPAREN);
389     }
390     else
391     {
392         e.getRight().accept(*this);
393     }
394     printer.handleExpEnd(&e);
395 }
396
397 void CodePrinterVisitor::visit(const ast::AssignExp & e)
398 {
399     printer.handleExpStart(&e);
400     e.getLeftExp().accept(*this);
401     printer.handleNothing(" ");
402     printer.handleOperator(SCI_ASSIGN);
403     printer.handleNothing(" ");
404     e.getRightExp().accept(*this);
405     printer.handleExpEnd(&e);
406 }
407
408 void CodePrinterVisitor::visit(const ast::CellCallExp & e)
409 {
410     printer.handleExpStart(&e);
411     e.getName().accept(*this);
412     printer.handleOpenClose(SCI_OPEN_CELL);
413     const ast::exps_t & args = e.getArgs();
414     if (args.size())
415     {
416         ast::exps_t::const_iterator last = std::prev(args.end());
417         for (ast::exps_t::const_iterator i = args.begin(), e = args.end(); i != e; ++i)
418         {
419             (*i)->accept(*this);
420             if (i != last)
421             {
422                 printer.handleDefault(SCI_COMMA);
423                 printer.handleNothing(" ");
424             }
425         }
426     }
427     printer.handleOpenClose(SCI_CLOSE_CELL);
428     printer.handleExpEnd(&e);
429 }
430
431 void CodePrinterVisitor::visit(const ast::CallExp & e)
432 {
433     printer.handleExpStart(&e);
434     e.getName().accept(*this);
435     printer.handleOpenClose(SCI_OPEN_CALL);
436     const ast::exps_t & args = e.getArgs();
437     if (args.size())
438     {
439         ast::exps_t::const_iterator last = std::prev(args.end());
440         for (ast::exps_t::const_iterator i = args.begin(), e = args.end(); i != e; ++i)
441         {
442             (*i)->accept(*this);
443             if (i != last)
444             {
445                 printer.handleDefault(SCI_COMMA);
446                 printer.handleNothing(" ");
447             }
448         }
449     }
450     printer.handleOpenClose(SCI_CLOSE_CALL);
451     printer.handleExpEnd(&e);
452 }
453
454 void CodePrinterVisitor::visit(const ast::IfExp & e)
455 {
456     printer.handleExpStart(&e);
457     printer.handleStructureKwds(SCI_IF);
458     printer.handleNothing(" ");
459     //printer.handleOpenClose(SCI_OPEN_TEST);
460     e.getTest().accept(*this);
461     //printer.handleOpenClose(SCI_CLOSE_TEST);
462     printer.handleNothing(" ");
463     printer.handleStructureKwds(SCI_THEN);
464
465     printer.incIndent();
466     printer.handleNewLine();
467     e.getThen().accept(*this);
468     printer.decIndent();
469     printer.handleNewLine();
470
471     if (e.hasElse() && !e.getElse().isCommentExp())
472     {
473         printer.handleStructureKwds(SCI_ELSE);
474         printer.incIndent();
475         printer.handleNewLine();
476         e.getElse().accept(*this);
477         printer.decIndent();
478         printer.handleNewLine();
479     }
480
481     printer.handleStructureKwds(SCI_ENDIF);
482     printer.handleExpEnd(&e);
483 }
484
485 void CodePrinterVisitor::visit(const ast::TryCatchExp & e)
486 {
487     printer.handleExpStart(&e);
488     printer.handleStructureKwds(SCI_TRY);
489
490     printer.incIndent();
491     printer.handleNewLine();
492     e.getTry().accept(*this);
493     printer.decIndent();
494     printer.handleNewLine();
495
496     printer.handleStructureKwds(SCI_CATCH);
497
498     printer.incIndent();
499     printer.handleNewLine();
500     e.getCatch().accept(*this);
501     printer.decIndent();
502     printer.handleNewLine();
503
504     printer.handleStructureKwds(SCI_ENDTRY);
505     printer.handleExpEnd(&e);
506 }
507
508 void CodePrinterVisitor::visit(const ast::WhileExp & e)
509 {
510     printer.handleExpStart(&e);
511     printer.handleStructureKwds(SCI_WHILE);
512     printer.handleNothing(" ");
513     //printer.handleOpenClose(SCI_OPEN_TEST);
514     e.getTest().accept(*this);
515     //printer.handleOpenClose(SCI_CLOSE_TEST);
516
517     printer.incIndent();
518     printer.handleNewLine();
519     e.getBody().accept(*this);
520     printer.decIndent();
521     printer.handleNewLine();
522
523     printer.handleStructureKwds(SCI_ENDWHILE);
524     printer.handleExpEnd(&e);
525 }
526
527 void CodePrinterVisitor::visit(const ast::ForExp & e)
528 {
529     printer.handleExpStart(&e);
530     printer.handleStructureKwds(SCI_FOR);
531     printer.handleNothing(" ");
532     e.getVardec().accept(*this);
533     printer.handleNothing(" ");
534     printer.handleStructureKwds(SCI_DO);
535
536     printer.incIndent();
537     printer.handleNewLine();
538     e.getBody().accept(*this);
539     printer.decIndent();
540     printer.handleNewLine();
541
542     printer.handleStructureKwds(SCI_ENDFOR);
543     printer.handleExpEnd(&e);
544 }
545
546 void CodePrinterVisitor::visit(const ast::BreakExp & e)
547 {
548     printer.handleExpStart(&e);
549     printer.handleControlKwds(SCI_BREAK);
550     printer.handleExpEnd(&e);
551 }
552
553 void CodePrinterVisitor::visit(const ast::ContinueExp & e)
554 {
555     printer.handleExpStart(&e);
556     printer.handleControlKwds(SCI_CONTINUE);
557     printer.handleExpEnd(&e);
558 }
559
560 void CodePrinterVisitor::visit(const ast::ReturnExp & e)
561 {
562     printer.handleExpStart(&e);
563     printer.handleControlKwds(SCI_RETURN);
564
565     if (!e.isGlobal())
566     {
567         printer.handleNothing(" ");
568         e.getExp().accept(*this);
569     }
570     printer.handleExpEnd(&e);
571 }
572
573 void CodePrinterVisitor::visit(const ast::SelectExp & e)
574 {
575     printer.handleExpStart(&e);
576     printer.handleStructureKwds(SCI_SELECT);
577     printer.handleNothing(" ");
578     printer.handleOpenClose(SCI_OPEN_TEST);
579     e.getSelect()->accept(*this);
580     printer.handleOpenClose(SCI_CLOSE_TEST);
581
582     printer.incIndent();
583     printer.handleNewLine();
584
585     ast::exps_t cases = e.getCases();
586     for (auto exp : cases)
587     {
588         exp->accept(*this);
589     }
590
591     if (e.hasDefault())
592     {
593         printer.handleStructureKwds(SCI_DEFAULT_CASE);
594         printer.incIndent();
595         printer.handleNewLine();
596         e.getDefaultCase()->accept(*this);
597         printer.decIndent();
598         printer.handleNewLine();
599     }
600
601     printer.decIndent();
602     printer.handleNewLine();
603     printer.handleStructureKwds(SCI_ENDSELECT);
604     printer.handleExpEnd(&e);
605 }
606
607 void CodePrinterVisitor::visit(const ast::CaseExp & e)
608 {
609     printer.handleExpStart(&e);
610     printer.handleStructureKwds(SCI_CASE);
611     printer.handleNothing(" ");
612     e.getTest()->accept(*this);
613
614     printer.incIndent();
615     printer.handleNewLine();
616     e.getBody()->accept(*this);
617     printer.decIndent();
618     printer.handleNewLine();
619     printer.handleExpEnd(&e);
620 }
621
622 void CodePrinterVisitor::visit(const ast::SeqExp & e)
623 {
624     printer.handleExpStart(&e);
625     const ast::exps_t & exps = e.getExps();
626     if (exps.size())
627     {
628         ast::exps_t::const_iterator last = std::prev(exps.end());
629         for (ast::exps_t::const_iterator i = exps.begin(), e = exps.end(); i != e; ++i)
630         {
631             (*i)->accept(*this);
632             if (!(*i)->isCommentExp() && !(*i)->isIfExp() && !(*i)->isForExp() && !(*i)->isWhileExp() && !(*i)->isTryCatchExp() && !(*i)->isFunctionDec())
633             {
634                 printer.handleNothing(";");
635             }
636
637             if (i != last)
638             {
639                 printer.handleNewLine();
640             }
641         }
642     }
643
644     printer.handleExpEnd(&e);
645 }
646
647 void CodePrinterVisitor::visit(const ast::ArrayListExp & e)
648 {
649     printer.handleExpStart(&e);
650     printer.handleOpenClose(SCI_LPAREN);
651     const ast::exps_t & exps = e.getExps();
652     if (exps.size())
653     {
654         ast::exps_t::const_iterator last = std::prev(exps.end());
655         for (ast::exps_t::const_iterator i = exps.begin(), e = exps.end(); i != e; ++i)
656         {
657             (*i)->accept(*this);
658             if (i != last)
659             {
660                 printer.handleDefault(SCI_COMMA);
661                 printer.handleNothing(" ");
662             }
663         }
664     }
665
666     printer.handleOpenClose(SCI_RPAREN);
667     printer.handleExpEnd(&e);
668 }
669
670 void CodePrinterVisitor::visit(const ast::AssignListExp & e)
671 {
672     printer.handleExpStart(&e);
673     printer.handleOpenClose(SCI_LBRACK);
674     const ast::exps_t & exps = e.getExps();
675     if (exps.size())
676     {
677         ast::exps_t::const_iterator last = std::prev(exps.end());
678         for (ast::exps_t::const_iterator i = exps.begin(), e = exps.end(); i != e; ++i)
679         {
680             (*i)->getOriginal()->accept(*this);
681             if (i != last)
682             {
683                 printer.handleDefault(SCI_COMMA);
684                 printer.handleNothing(" ");
685             }
686         }
687     }
688
689     printer.handleOpenClose(SCI_RBRACK);
690     printer.handleExpEnd(&e);
691 }
692
693 void CodePrinterVisitor::visit(const ast::NotExp & e)
694 {
695     printer.handleExpStart(&e);
696     printer.handleOperator(SCI_NOT);
697     if (e.getExp().isOpExp() || e.getExp().isLogicalOpExp())
698     {
699         printer.handleOpenClose(SCI_LPAREN);
700         e.getExp().accept(*this);
701         printer.handleOpenClose(SCI_RPAREN);
702     }
703     else
704     {
705         e.getExp().accept(*this);
706     }
707     printer.handleExpEnd(&e);
708 }
709
710 void CodePrinterVisitor::visit(const ast::TransposeExp & e)
711 {
712     printer.handleExpStart(&e);
713     if (e.getExp().isOpExp() || e.getExp().isLogicalOpExp())
714     {
715         printer.handleOpenClose(SCI_LPAREN);
716         e.getExp().accept(*this);
717         printer.handleOpenClose(SCI_RPAREN);
718     }
719     else
720     {
721         e.getExp().accept(*this);
722     }
723
724     if (e.getConjugate() == ast::TransposeExp::_Conjugate_)
725     {
726         printer.handleOperator(SCI_CONJUGATE_TRANSPOSE);
727     }
728     else if (e.getConjugate() == ast::TransposeExp::_NonConjugate_)
729     {
730         printer.handleOperator(SCI_TRANSPOSE);
731     }
732     printer.handleExpEnd(&e);
733 }
734
735 void CodePrinterVisitor::visit(const ast::VarDec & e)
736 {
737     printer.handleExpStart(&e);
738     printer.handleName(e.getSymbol().getName());
739     printer.handleNothing(" ");
740     printer.handleOperator(SCI_ASSIGN);
741     printer.handleNothing(" ");
742     e.getInit().accept(*this);
743     printer.handleExpEnd(&e);
744 }
745
746 void CodePrinterVisitor::visit(const ast::FunctionDec & e)
747 {
748     printer.handleExpStart(&e);
749     printer.handleFunctionKwds(SCI_FUNCTION);
750     printer.handleNothing(" ");
751     const ast::ArrayListVar & ret = e.getReturns();
752     const ast::ArrayListVar & args = e.getArgs();
753
754     if (ret.getVars().size() > 1)
755     {
756         printer.handleOpenClose(SCI_OPEN_RETURNS);
757         ret.accept(*this);
758         printer.handleOpenClose(SCI_CLOSE_RETURNS);
759     }
760     else
761     {
762         ret.accept(*this);
763     }
764
765     if (ret.getVars().size() != 0)
766     {
767         printer.handleNothing(" ");
768         printer.handleOperator(SCI_ASSIGN);
769         printer.handleNothing(" ");
770     }
771
772     printer.handleFunctionNameDec(e.getSymbol().getName());
773
774     printer.handleOpenClose(SCI_OPEN_ARGS);
775     args.accept(*this);
776     printer.handleOpenClose(SCI_CLOSE_ARGS);
777
778     printer.incIndent();
779     printer.handleNewLine();
780     e.getBody().accept(*this);
781     printer.decIndent();
782     printer.handleNewLine();
783
784     printer.handleFunctionKwds(SCI_ENDFUNCTION);
785     printer.handleExpEnd(&e);
786 }
787
788 void CodePrinterVisitor::visit(const ast::ListExp & e)
789 {
790     printer.handleExpStart(&e);
791     if (e.getStart().isOpExp() || e.getStart().isLogicalOpExp())
792     {
793         printer.handleOpenClose(SCI_LPAREN);
794         e.getStart().accept(*this);
795         printer.handleOpenClose(SCI_RPAREN);
796     }
797     else
798     {
799         e.getStart().accept(*this);
800     }
801
802     if (e.hasExplicitStep())
803     {
804         printer.handleOperator(SCI_IMPLICIT_LIST);
805         if (e.getStep().isOpExp() || e.getStep().isLogicalOpExp())
806         {
807             printer.handleOpenClose(SCI_LPAREN);
808             e.getStep().accept(*this);
809             printer.handleOpenClose(SCI_RPAREN);
810         }
811         else
812         {
813             e.getStep().accept(*this);
814         }
815     }
816
817     printer.handleOperator(SCI_IMPLICIT_LIST);
818     if (e.getEnd().isOpExp() || e.getEnd().isLogicalOpExp())
819     {
820         printer.handleOpenClose(SCI_LPAREN);
821         e.getEnd().accept(*this);
822         printer.handleOpenClose(SCI_RPAREN);
823     }
824     else
825     {
826         e.getEnd().accept(*this);
827     }
828     printer.handleExpEnd(&e);
829 }
830
831 void CodePrinterVisitor::visit(const ast::OptimizedExp & e)
832 {
833     printer.handleExpStart(&e);
834     e.getOriginal()->accept(*this);
835     printer.handleExpEnd(&e);
836 }
837
838 void CodePrinterVisitor::visit(const ast::DAXPYExp & e)
839 {
840     printer.handleExpStart(&e);
841     e.getOriginal()->accept(*this);
842     printer.handleExpEnd(&e);
843 }
844
845 void CodePrinterVisitor::visit(const ast::MemfillExp & e)
846 {
847     printer.handleExpStart(&e);
848     e.getOriginal()->accept(*this);
849     printer.handleExpEnd(&e);
850 }
851
852 void CodePrinterVisitor::visit(const ast::IntSelectExp & e)
853 {
854     printer.handleExpStart(&e);
855     e.getOriginal()->accept(*this);
856     printer.handleExpEnd(&e);
857 }
858
859 void CodePrinterVisitor::visit(const ast::StringSelectExp & e)
860 {
861     printer.handleExpStart(&e);
862     e.getOriginal()->accept(*this);
863     printer.handleExpEnd(&e);
864 }
865 }