License Header change: Removed the LICENSE_END before beta
[scilab.git] / scilab / modules / ast / src / cpp / analysis / OperAnalyzer.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 "AnalysisVisitor.hxx"
17 #include "analyzers/OperAnalyzer.hxx"
18 #include "allexp.hxx"
19 #include "allvar.hxx"
20 #include "alltypes.hxx"
21
22 namespace analysis
23 {
24 bool OperAnalyzer::analyze(AnalysisVisitor & visitor, ast::Exp & e)
25 {
26     ast::OpExp & oe = static_cast<ast::OpExp &>(e);
27     const ast::OpExp::Oper oper = oe.getOper();
28     if (oper == ast::OpExp::plus || oper == ast::OpExp::minus || oper == ast::OpExp::times)
29     {
30         if (ast::MemfillExp * mfe = analyzeMemfill(visitor, oe))
31         {
32             mfe->setVerbose(e.isVerbose());
33             e.replace(mfe);
34
35             return true;
36         }
37     }
38
39     /*if (ast::ExtendedOpExp * eoe = analyzeMemfill(visitor, oe))
40       {
41       eoe->setVerbose(e.isVerbose());
42       e.replace(eoe);
43
44       return true;
45       }*/
46
47     return false;
48 }
49
50 /*ast::ExtendedOpExp * OperAnalyzer::analyzeTransposedArgs(ast::OpExp & oe)
51   {
52   ast::Exp & L = oe.getLeft();
53   ast::Exp & R = oe.getRight();
54   ast::ExtendedOpExp::OP Lop, Rop;
55   ast::Exp * Le = &L;
56   ast::Exp * Re = &R;
57
58   if (L.isTransposeExp())
59   {
60   ast::TransposeExp & te = static_cast<ast::TransposeExp &>(L);
61   if (te.getConjugate() == ast::TransposeExp::_Conjugate_)
62   {
63   Lop = ast::ExtendedOpExp::ADJOINT;
64   }
65   else
66   {
67   Lop = ast::ExtendedOpExp::TRANSP;
68   }
69   Le = &te.getExp();
70   }
71
72   if (R.isTransposeExp())
73   {
74   ast::TransposeExp & te = static_cast<ast::TransposeExp &>(R);
75   if (te.getConjugate() == ast::TransposeExp::_Conjugate_)
76   {
77   Rop = ast::ExtendedOpExp::ADJOINT;
78   }
79   else
80   {
81   Rop = ast::ExtendedOpExp::TRANSP;
82   }
83   Re = &te.getExp();
84   }
85
86   if (Lop != ast::ExtendedOpExp::NONE || Rop != ast::ExtendedOpExp::NONE)
87   {
88   return new ast::ExtendedOpExp(oe.getLocation(), *Le, Lop, oe.getOper(), *Re, Rop);
89   }
90
91   return nullptr;
92   }*/
93
94 ast::MemfillExp * OperAnalyzer::analyzeMemfill(AnalysisVisitor & visitor, ast::OpExp & oe)
95 {
96     const ast::OpExp::Oper oper = oe.getOper();
97     ast::Exp & L = oe.getLeft();
98     ast::Exp & R = oe.getRight();
99
100     ast::Exp * constant = nullptr;
101     ast::MemfillExp * me = nullptr;
102     ast::exps_t args;
103     double value;
104     bool callAtLeft;
105
106     // We try to match something like A +* ones(...) or A +* zeros(...)
107     if (L.isCallExp())
108     {
109         ast::CallExp & ce = static_cast<ast::CallExp &>(L);
110         if (ce.getName().isSimpleVar())
111         {
112             const std::wstring & name = static_cast<ast::SimpleVar &>(ce.getName()).getSymbol().getName();
113             if (name == L"ones")
114             {
115                 value = 1;
116                 args = ce.getArgs();
117                 constant = &R;
118                 callAtLeft = true;
119             }
120             else if (name == L"zeros")
121             {
122                 value = 0;
123                 args = ce.getArgs();
124                 constant = &R;
125                 callAtLeft = true;
126             }
127         }
128     }
129
130     if (!constant)
131     {
132         if (R.isCallExp())
133         {
134             ast::CallExp & ce = static_cast<ast::CallExp &>(R);
135             if (ce.getName().isSimpleVar())
136             {
137                 const std::wstring & name = static_cast<ast::SimpleVar &>(ce.getName()).getSymbol().getName();
138                 if (name == L"ones")
139                 {
140                     value = 1;
141                     args = ce.getArgs();
142                     constant = &L;
143                     callAtLeft = false;
144                 }
145                 else if (name == L"zeros")
146                 {
147                     value = 0;
148                     args = ce.getArgs();
149                     constant = &L;
150                     callAtLeft = false;
151                 }
152             }
153         }
154     }
155
156     if (constant && (oper == ast::OpExp::plus || oper == ast::OpExp::minus || oper == ast::OpExp::times))
157     {
158         Result & res = constant->getDecorator().getResult();
159         if (res.getType().ismatrix() && res.getType().isscalar())
160         {
161             TIType ty(visitor.getGVN(), TIType::DOUBLE);
162             ast::exps_t cloneArgs;
163             cloneArgs.reserve(args.size());
164             for (auto arg : args)
165             {
166                 ast::Exp * cl = arg->clone();
167                 cl->getDecorator().setResult(arg->getDecorator().getResult());
168                 cloneArgs.push_back(cl);
169             }
170
171             switch (oper)
172             {
173                 case ast::OpExp::plus :
174                 {
175                     // plus is commutative so callAtLeft is ignored
176                     // we have something like x + ones(...) => it is a fill with x+1
177                     const Location & loc = oe.getLocation();
178                     ast::Exp * valExp;
179                     double x;
180                     if (res.getConstant().getDblValue(x))
181                     {
182                         valExp = new ast::DoubleExp(loc, new types::Double(x + value));
183                         valExp->getDecorator().setResult(Result(ty));
184                     }
185                     else
186                     {
187                         ast::Exp * cl = constant->clone();
188                         cl->getDecorator().setResult(constant->getDecorator().getResult());
189                         valExp = new ast::DoubleExp(loc, new types::Double(value));
190                         valExp->getDecorator().setResult(Result(ty));
191                         valExp = new ast::OpExp(loc, *cl, ast::OpExp::plus, *valExp);
192                         valExp->getDecorator().setResult(Result(Checkers::check_____add____(visitor.getGVN(), cl->getDecorator().getResult().getType(), ty)));
193                     }
194                     me = new ast::MemfillExp(loc, *valExp, cloneArgs);
195                     break;
196                 }
197                 case ast::OpExp::minus :
198                 {
199                     // we have something like x - ones(...) => it is a fill with x-1
200                     const Location & loc = oe.getLocation();
201                     ast::Exp * valExp;
202                     double x;
203                     if (res.getConstant().getDblValue(x))
204                     {
205                         valExp = new ast::DoubleExp(loc, new types::Double(callAtLeft ? value - x : x - value));
206                         valExp->getDecorator().setResult(Result(ty));
207                     }
208                     else
209                     {
210                         ast::Exp * cl = constant->clone();
211                         cl->getDecorator().setResult(constant->getDecorator().getResult());
212                         valExp = new ast::DoubleExp(loc, new types::Double(value));
213                         valExp->getDecorator().setResult(Result(ty));
214                         if (callAtLeft)
215                         {
216                             valExp = new ast::OpExp(loc, *valExp, ast::OpExp::minus, *cl);
217                             valExp->getDecorator().setResult(Result(Checkers::check_____sub____(visitor.getGVN(), ty, cl->getDecorator().getResult().getType())));
218                         }
219                         else
220                         {
221                             valExp = new ast::OpExp(loc, *cl, ast::OpExp::minus, *valExp);
222                             valExp->getDecorator().setResult(Result(Checkers::check_____sub____(visitor.getGVN(), cl->getDecorator().getResult().getType(), ty)));
223                         }
224                     }
225                     me = new ast::MemfillExp(loc, *valExp, cloneArgs);
226                     break;
227                 }
228                 case ast::OpExp::times :
229                 {
230                     // times is commutative so callAtLeft is ignored
231                     // we have something like x * ones(...) => it is a fill with x
232                     const Location & loc = oe.getLocation();
233                     ast::Exp * valExp;
234                     double x = 0;
235                     if (value == 0 || res.getConstant().getDblValue(x))
236                     {
237                         valExp = new ast::DoubleExp(loc, new types::Double(x * value));
238                         valExp->getDecorator().setResult(Result(ty));
239                     }
240                     else
241                     {
242                         valExp = constant->clone();
243                         valExp->getDecorator().setResult(constant->getDecorator().getResult());
244                     }
245                     me = new ast::MemfillExp(loc, *valExp, cloneArgs);
246                     break;
247                 }
248             }
249
250             if (me)
251             {
252                 if (callAtLeft)
253                 {
254                     ast::CallExp & ce = static_cast<ast::CallExp &>(L);
255                     me->getDecorator().setResult(ce.getDecorator().getResult());
256                 }
257                 else
258                 {
259                     ast::CallExp & ce = static_cast<ast::CallExp &>(R);
260                     me->getDecorator().setResult(ce.getDecorator().getResult());
261                 }
262             }
263         }
264     }
265
266     return me;
267 }
268 }