Analysis: replace constant in Result by a C++ union
[scilab.git] / scilab / modules / ast / src / cpp / analysis / VisitListExp.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2014 - Scilab Enterprises - Calixte DENIZET
4  *
5  *  This file must be used under the terms of the CeCILL.
6  *  This source file is licensed as described in the file COPYING, which
7  *  you should have received as part of this distribution.  The terms
8  *  are also available at
9  *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12
13 #include "AnalysisVisitor.hxx"
14 #include "tools.hxx"
15
16 namespace analysis
17 {
18 void AnalysisVisitor::visit(ast::ListExp & e)
19 {
20     double start, step, end;
21     if (AnalysisVisitor::asDouble(e.getStart(), start) && AnalysisVisitor::asDouble(e.getStep(), step) && AnalysisVisitor::asDouble(e.getEnd(), end))
22     {
23         double out;
24         int type = ForList64::checkList(start, end, step, out);
25
26         switch (type)
27         {
28             case 0:
29                 e.getDecorator().setResult(Result(TIType(dm.getGVN(), TIType::EMPTY), -1));
30                 break;
31             case 1:
32                 e.getDecorator().setResult(Result(TIType(dm.getGVN(), TIType::DOUBLE), -1));
33                 break;
34             case 2:
35             {
36                 const uint64_t N = ForList64::size(start, end, step);
37                 TIType T(dm.getGVN(), TIType::DOUBLE, 1, N);
38                 if (N == 1)
39                 {
40                     out = start;
41                 }
42                 e.getDecorator().setResult(Result(T, temp.add(T)));
43                 break;
44             }
45             default:
46                 break;
47         }
48         e.setValues(start, step, end, out);
49         setResult(e.getDecorator().res);
50
51         return;
52     }
53
54     e.getStart().accept(*this);
55     Result Rstart = getResult();
56
57     if (!AnalysisVisitor::asDouble(e.getStep(), step) || (step != -1 && step != 1))
58     {
59         Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false, true), -1));
60         setResult(res);
61         return;
62     }
63
64     GVN::Value * gvnStart;
65
66     if (!Rstart.getType().isscalar())
67     {
68         Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false, true), -1));
69         setResult(res);
70         return;
71     }
72
73     if (Rstart.getConstant().getDblValue(start))
74     {
75         if (tools::getIntType(start) == tools::NOTANINT)
76         {
77             gvnStart = getGVN().getValue((double)tools::cast<int>(start + step));
78         }
79         else
80         {
81             gvnStart = getGVN().getValue((double)tools::cast<int>(start));
82         }
83     }
84     else
85     {
86         gvnStart = Rstart.getConstant().getGVNValue();
87         if (!gvnStart)
88         {
89             Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false, true), -1));
90             setResult(res);
91             return;
92         }
93     }
94
95     e.getEnd().accept(*this);
96     Result & Rend = getResult();
97     GVN::Value * gvnEnd;
98
99     if (Rend.getConstant().getDblValue(end))
100     {
101         if (tools::getIntType(end) == tools::NOTANINT)
102         {
103             gvnEnd = getGVN().getValue((double)tools::cast<int>(end - step));
104         }
105         else
106         {
107             gvnEnd = getGVN().getValue((double)tools::cast<int>(end));
108         }
109     }
110     else
111     {
112         gvnEnd = Rend.getConstant().getGVNValue();
113         if (!gvnEnd)
114         {
115             Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false, true), -1));
116             setResult(res);
117             return;
118         }
119     }
120
121     GVN::Value * ONEValue = getGVN().getValue(1.);
122     SymbolicDimension ONE(getGVN(), ONEValue);
123     GVN::Value * v;
124     if (step == 1)
125     {
126         v = getGVN().getValue(OpValue::Kind::MINUS, *gvnEnd, *gvnStart);
127     }
128     else
129     {
130         v = getGVN().getValue(OpValue::Kind::MINUS, *gvnStart, *gvnEnd);
131     }
132     v = getGVN().getValue(OpValue::Kind::PLUS, *v, *ONEValue);
133
134     if (v->poly->isConstant() && v->poly->constant <= 0)
135     {
136         TIType type(getGVN(), TIType::EMPTY);
137         e.getDecorator().res = Result(type);
138     }
139     else
140     {
141         bool res = getCM().check(ConstraintManager::POSITIVE, v);
142         if (res)
143         {
144             TIType type(getGVN(), TIType::DOUBLE, ONE, SymbolicDimension(getGVN(), v));
145             e.getDecorator().setResult(type);
146         }
147         else
148         {
149             Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false, true), -1));
150             setResult(res);
151             return;
152         }
153     }
154     setResult(e.getDecorator().res);
155 }
156 }