* Bug 15599 fixed: now degree of zero polynomial is -Inf
[scilab.git] / scilab / modules / ast / includes / ast / serializervisitor.hxx
1 /*
2  *  Scilab (http://www.scilab.org/) - This file is part of Scilab
3  *  Copyright (C) 2012-2013 - OCAMLPRO INRIA - Fabrice LE FESSANT
4  *  Copyright (C) 2014 - Scilab Enterprises - Antoine ELIAS
5  *
6  * Copyright (C) 2012 - 2016 - Scilab Enterprises
7  *
8  * This file is hereby licensed under the terms of the GNU GPL v2.0,
9  * pursuant to article 5.3.4 of the CeCILL v.2.1.
10  * This file was originally licensed under the terms of the CeCILL v2.1,
11  * and continues to be available under such terms.
12  * For more information, see the COPYING file which you should have received
13  * along with this program.
14  *
15  */
16
17 #ifndef __SERIALIZER_HXX__
18 #define __SERIALIZER_HXX__
19
20 #include "dummyvisitor.hxx"
21 #include "deserializervisitor.hxx"
22 #include "timer.hxx"
23 #include "charEncoding.h"
24 #include "version.h"
25
26 #define FAGMENT_SIZE 65536
27
28 namespace ast
29 {
30 class SerializeVisitor : public DummyVisitor
31 {
32 private :
33     Exp* ast;
34     unsigned char *buf;
35     int buflen;
36     int bufsize;
37     bool saveNodeNumber;
38     bool saveLocation;
39
40     unsigned char* get_buf(void)
41     {
42         // set buffer size
43         set_uint32(0, buflen);
44         // set scilab version
45         set_version();
46         return buf;
47     }
48
49     /** @{ Set the file header without modifying the file size. */
50
51     void set_version()
52     {
53         set_byte(4, (unsigned char)SCI_VERSION_MAJOR);
54         set_byte(5, (unsigned char)SCI_VERSION_MINOR);
55         set_byte(6, (unsigned char)SCI_VERSION_MAINTENANCE);
56         set_byte(7, (unsigned char)0);
57     }
58
59     void set_uint32(unsigned int pos, unsigned int n)
60     {
61         buf[pos++] = (n & 0xff);
62         n >>= 8;
63         buf[pos++] = (n & 0xff);
64         n >>= 8;
65         buf[pos++] = (n & 0xff);
66         n >>= 8;
67         buf[pos++] = (n & 0xff);
68     }
69
70     void set_byte(unsigned int pos, unsigned char n)
71     {
72         buf[pos] = n;
73     }
74
75     /** @} */
76
77     void add_location(const Location& loc)
78     {
79         if (saveLocation)
80         {
81             add_uint32(loc.first_line);
82             add_uint32(loc.first_column);
83             add_uint32(loc.last_line);
84             add_uint32(loc.last_column);
85         }
86         else
87         {
88             add_uint32(0);
89             add_uint32(0);
90             add_uint32(0);
91             add_uint32(0);
92         }
93     }
94     void add_ast(unsigned int code, const Exp& e)
95     {
96         add_uint8(code);
97         if (saveNodeNumber)
98         {
99             add_uint64(e.getNodeNumber());
100         }
101         else
102         {
103             add_uint64((unsigned long long)0);
104         }
105
106         add_location(e.getLocation());
107         add_uint8(e.isVerbose());
108     }
109
110     /** @{ Low-level append to the buffer functions */
111
112     /* ensure that we have [size] bytes in the buffer */
113     void need(int size)
114     {
115         if (bufsize - buflen < size)
116         {
117             bufsize = 2 * bufsize + size + FAGMENT_SIZE;
118             unsigned char *newbuf = (unsigned char*) malloc(bufsize * sizeof(unsigned char));
119             // std::cerr << "malloc " << (void*) newbuf << " " << bufsize << " " << (void*) buf << " " << buflen << std::endl;
120             if (buflen > 0)
121             {
122                 // std::cerr << "memcpy " << (void*) newbuf << " " << bufsize << " " << (void*) buf << " " << buflen << std::endl;
123                 memcpy(newbuf, buf, buflen);
124             }
125             if (buf != NULL)
126             {
127                 // std::cerr << "free " << (void*) newbuf << " " << bufsize << " " << (void*) buf << " " << buflen << std::endl;
128                 free(buf);
129             }
130             else
131             {
132                 buflen = 8;    /* Header length. Header =  final size of buf (4 bytes) + scilab version (4 bytes)*/
133             }
134             buf = newbuf;
135         }
136
137         // std::cerr << "need " << size << " " << bufsize << " " << (void*) buf << " " << buflen << std::endl;
138     }
139
140     void add_byte(unsigned char n)
141     {
142         buf[buflen++] = n;
143     }
144
145     void add_uint8(unsigned char n)
146     {
147         need(1);
148         add_byte(n);
149     }
150
151     void add_uint32(unsigned int n)
152     {
153         need(4);
154         add_byte(n & 0xff);
155         add_byte((n >>= 8) & 0xff);
156         add_byte((n >>= 8) & 0xff);
157         add_byte((n >>= 8) & 0xff);
158     }
159
160     void add_uint64(unsigned long long n)
161     {
162         need(8);
163         add_byte(n & 0xff);
164         add_byte((n >>= 8) & 0xff);
165         add_byte((n >>= 8) & 0xff);
166         add_byte((n >>= 8) & 0xff);
167         add_byte((n >>= 8) & 0xff);
168         add_byte((n >>= 8) & 0xff);
169         add_byte((n >>= 8) & 0xff);
170         add_byte((n >>= 8) & 0xff);
171     }
172
173     void add_double(double d)
174     {
175         need(8);
176         *(double*)(buf + buflen) = d;
177         buflen += 8;
178     }
179
180     void add_wstring(const std::wstring &w)
181     {
182         char *c_str = wide_string_to_UTF8(w.c_str());
183         int size = strlen(c_str);
184         int final_size = size * sizeof(char);
185         add_uint32(final_size);
186         need(final_size);
187         memcpy(buf + buflen, c_str, final_size);
188         FREE(c_str);
189         buflen += final_size;
190     }
191
192     /** @} */
193
194     void add_exps(const exps_t& exps)
195     {
196         add_uint32((unsigned int)exps.size());
197         if (exps.size() != 0)
198         {
199             for (auto exp : exps)
200             {
201                 exp->getOriginal()->accept(*this);
202             }
203         }
204     }
205
206     void add_vars(const ArrayListVar& var)
207     {
208         exps_t vars = var.getVars();
209         add_uint32((unsigned int)vars.size());
210         for (exps_t::const_iterator it = vars.begin (), itEnd = vars.end(); it != itEnd; ++it)
211         {
212             (*it)->getOriginal()->accept(*this);
213         }
214     }
215
216     void add_Symbol(const symbol::Symbol& e)
217     {
218         add_wstring(e.getName());
219     }
220
221     void add_exp(const Exp* e)
222     {
223         e->getOriginal()->accept(*this);
224     }
225
226     void add_exp(const Exp& e)
227     {
228         e.getOriginal()->accept(*this);
229     }
230
231     void add_OpExp_Oper(const OpExp::Oper oper)
232     {
233         int code = 253;
234         switch (oper)
235         {
236             case OpExp::plus :
237                 code = (1);
238                 break;
239             case OpExp::minus:
240                 code = (2);
241                 break;
242             case OpExp::times:
243                 code = (3);
244                 break;
245             case OpExp::rdivide:
246                 code = (4);
247                 break;
248             case OpExp::ldivide:
249                 code = (5);
250                 break;
251             case OpExp::power:
252                 code = (6);
253                 break;
254
255             case OpExp::dottimes:
256                 code = (7);
257                 break;
258             case OpExp::dotrdivide:
259                 code = (8);
260                 break;
261             case OpExp::dotldivide:
262                 code = (9);
263                 break;
264             case OpExp::dotpower:
265                 code = (10);
266                 break;
267
268             case OpExp::krontimes:
269                 code = (11);
270                 break;
271             case OpExp::kronrdivide:
272                 code = (12);
273                 break;
274             case OpExp::kronldivide:
275                 code = (13);
276                 break;
277
278             case OpExp::controltimes:
279                 code = (14);
280                 break;
281             case OpExp::controlrdivide:
282                 code = (15);
283                 break;
284             case OpExp::controlldivide:
285                 code = (16);
286                 break;
287
288             case OpExp::eq:
289                 code = (17);
290                 break;
291             case OpExp::ne:
292                 code = (18);
293                 break;
294             case OpExp::lt:
295                 code = (19);
296                 break;
297             case OpExp::le:
298                 code = (20);
299                 break;
300             case OpExp::gt:
301                 code = (21);
302                 break;
303             case OpExp::ge:
304                 code = (22);
305                 break;
306
307             case OpExp::unaryMinus:
308                 code = (23);
309                 break;
310
311             case OpExp::logicalAnd:
312                 code = (24);
313                 break;
314             case OpExp::logicalOr:
315                 code = (25);
316                 break;
317             case OpExp::logicalShortCutAnd:
318                 code = (26);
319                 break;
320             case OpExp::logicalShortCutOr:
321                 code = (27);
322                 break;
323         }
324         add_uint8(code);
325     }
326
327     void add_TransposeExp_Kind(const TransposeExp::Kind kind)
328     {
329         int code = 249;
330         switch (kind)
331         {
332             case TransposeExp::_Conjugate_ :
333                 code = (1);
334                 break;
335             case TransposeExp::_NonConjugate_:
336                 code = (2);
337                 break;
338         }
339         add_uint8(code);
340     }
341
342     void add_bool(bool b)
343     {
344         add_uint8(b);
345     }
346
347     void add_varDec(const VarDec& varDec)
348     {
349         add_Symbol(varDec.getSymbol());
350         add_exp(varDec.getInit());
351     }
352
353     void add_MatrixLines(const exps_t* lines)
354     {
355         add_uint32((unsigned int)lines->size());
356         for (exps_t::const_iterator it = lines->begin(), itEnd = lines->end(); it != itEnd ; ++it)
357         {
358             add_location((*it)->getLocation());
359             add_exps((*it)->getAs<MatrixLineExp>()->getColumns());
360         }
361     }
362
363     virtual void visit (const SeqExp &e)  /* done */
364     {
365         add_ast(1, e);
366         add_exps(e.getExps());
367     }
368     void visit(const StringExp& e)  /* done */
369     {
370         add_ast(2, e);
371         add_wstring(e.getValue());
372     }
373     void visit(const CommentExp& e)  /* done */
374     {
375         add_ast(3, e);
376         add_wstring(e.getComment());
377     }
378     void visit(const DoubleExp& e)  /* done */
379     {
380         add_ast(6, e);
381         add_double(e.getValue());
382     }
383     void visit(const BoolExp& e)  /* done */
384     {
385         add_ast(7, e);
386         add_bool(e.getValue());
387     }
388     void visit(const NilExp& e)  /* done */
389     {
390         add_ast(8, e);
391     }
392     void visit(const SimpleVar& e)  /* done */
393     {
394         add_ast(9, e);
395         add_Symbol(e.getSymbol());
396     }
397     void visit(const ColonVar& e)  /* done */
398     {
399         add_ast(10, e);
400     }
401     void visit(const DollarVar& e)  /* done */
402     {
403         add_ast(11, e);
404     }
405     void visit(const ArrayListVar& e)  /* done */
406     {
407         add_ast(12, e);
408         add_vars(e);
409     }
410     void visit(const FieldExp& e)  /* done */
411     {
412         add_ast(13, e);
413         add_exp(e.getHead());
414         add_exp(e.getTail());
415     }
416     void visit(const IfExp& e)  /* done */
417     {
418         add_ast(14, e);
419         bool hasElse = e.hasElse();
420         add_bool(hasElse);
421         add_exp(& e.getTest());
422         add_exp(& e.getThen());
423         if (hasElse)
424         {
425             add_exp(& e.getElse());
426         }
427     }
428     void visit(const TryCatchExp& e)  /* done */
429     {
430         add_ast(15, e);
431         add_location(e.getTry().getLocation());
432         add_location(e.getCatch().getLocation());
433         add_exps(e.getTry().getAs<SeqExp>()->getExps());
434         add_exps(e.getCatch().getAs<SeqExp>()->getExps());
435     }
436     void visit(const WhileExp& e)  /* done */
437     {
438         add_ast(16, e);
439         add_exp(& e.getTest());
440         add_exp(& e.getBody());
441     }
442     void visit(const ForExp& e)   /* done */
443     {
444         add_ast(17, e);
445         add_location(e.getVardec().getLocation());
446         add_varDec(*e.getAs<ForExp>()->getVardec().getAs<VarDec>());
447         add_exp(&e.getBody());
448     }
449     void visit(const BreakExp& e)  /* done */
450     {
451         add_ast(18, e);
452     }
453     void visit(const ContinueExp& e)  /* done */
454     {
455         add_ast(19, e);
456     }
457     void visit(const ReturnExp& e)  /* done */
458     {
459         add_ast(20, e);
460         bool is_global = e.isGlobal();
461         add_bool(is_global);
462         if (!is_global) /* otherwise exp is NULL */
463         {
464             add_exp(& e.getExp());
465         }
466     }
467     void visit(const SelectExp& e)
468     {
469         add_ast(21, e);
470         Exp *default_case = e.getDefaultCase();
471         add_bool(e.hasDefault());
472         if (e.hasDefault())
473         {
474             add_location(default_case->getLocation());
475             add_exps(default_case->getAs<SeqExp>()->getExps());
476         }
477         add_exp(e.getSelect());
478
479         exps_t cases = e.getCases();
480         add_uint32((unsigned int)cases.size());
481
482         for (auto exp : cases)
483         {
484             const CaseExp *ce = exp->getAs<CaseExp>();
485             add_location(ce->getLocation());
486             add_location(ce->getBody()->getLocation());
487             add_exp(ce->getTest());
488             add_exps(ce->getBody()->getAs<SeqExp>()->getExps());
489         }
490     }
491     void visit(const CellExp& e)  /* done */
492     {
493         add_ast(23, e);
494         add_MatrixLines(& e.getLines());
495     }
496     void visit(const ArrayListExp& e)  /* done */
497     {
498         add_ast(24, e);
499         add_exps(e.getExps());
500     }
501     void visit(const AssignListExp& e)  /* done */
502     {
503         add_ast(25, e);
504         add_exps(e.getExps());
505     }
506     void visit(const NotExp& e)  /* done */
507     {
508         add_ast(26, e);
509         add_exp(e.getExp());
510     }
511     void visit(const TransposeExp& e)  /* done */
512     {
513         add_ast(27, e);
514         add_TransposeExp_Kind(e.getConjugate());
515         add_exp(e.getExp());
516     }
517     void visit(const VarDec& e)
518     {
519         add_ast(28, e);
520         add_varDec(e);
521     }
522     void visit(const FunctionDec& e)  /* done */
523     {
524         add_ast(29, e);
525         add_Symbol(e.getSymbol());
526         add_location(e.getArgs().getLocation());
527         add_location(e.getReturns().getLocation());
528         add_exp(e.getBody());
529         add_vars(*e.getArgs().getAs<ArrayListVar>());
530         add_vars(*e.getReturns().getAs<ArrayListVar>());
531     }
532     void visit(const ListExp& e)  /* done */
533     {
534         add_ast(30, e);
535         add_exp(e.getStart());
536         add_exp(e.getStep());
537         add_exp(e.getEnd());
538     }
539     void visit(const AssignExp& e)
540     {
541         add_ast(31, e);
542         add_exp(e.getLeftExp());
543         add_exp(e.getRightExp());
544     }
545     void visit(const OpExp& e)  /* done */
546     {
547         add_ast(32, e);
548         add_OpExp_Oper(e.getOper());
549         e.getLeft().getOriginal()->accept(*this);
550         e.getRight().getOriginal()->accept(*this);
551     }
552     void visit(const LogicalOpExp& e)  /* done */
553     {
554         add_ast(33, e);
555         add_OpExp_Oper(e.getOper());
556         e.getLeft().getOriginal()->accept(*this);
557         e.getRight().getOriginal()->accept(*this);
558     }
559     void visit(const MatrixExp& e) /* done */
560     {
561         add_ast(34, e);
562         add_MatrixLines(& e.getLines());
563     }
564     void visit(const CallExp& e)  /* done */
565     {
566         add_ast(35, e);
567         add_exp(e.getName());
568         ast::exps_t args = e.getArgs();
569         add_exps(args);
570     }
571     void visit(const MatrixLineExp& e)  /* SHOULD NEVER HAPPEN */
572     {
573         add_ast(36, e);
574     }
575     void visit(const CellCallExp& e)  /* done */
576     {
577         add_ast(37, e);
578         add_exp(e.getName());
579         ast::exps_t args = e.getArgs();
580         add_exps(args);
581     }
582
583     /* optimized */
584     void visit(const OptimizedExp& e)
585     {
586         e.getOriginal()->accept(*this);
587     }
588
589     void visit(const MemfillExp& e)
590     {
591         e.getOriginal()->accept(*this);
592     }
593
594     void visit(const DAXPYExp& e)
595     {
596         e.getOriginal()->accept(*this);
597     }
598
599     void visit(const IntSelectExp& e)
600     {
601         e.getOriginal()->accept(*this);
602     }
603
604     void visit(const StringSelectExp& e)
605     {
606         e.getOriginal()->accept(*this);
607     }
608
609 public :
610     SerializeVisitor(Exp* _ast) : ast(_ast), buf(NULL), buflen(0), bufsize(0), saveNodeNumber(true), saveLocation(true) {}
611
612     SerializeVisitor* clone()
613     {
614         return new SerializeVisitor(ast);
615     }
616
617     unsigned char* serialize(bool _saveNodeNumber = true, bool _saveLocation = true)
618     {
619         saveNodeNumber = _saveNodeNumber;
620         saveLocation = _saveLocation;
621         ast->getOriginal()->accept(*this);
622         return get_buf();
623     }
624 };
625 }
626
627 #endif /* !__SERIALIZER_HXX__ */