Analysis: fix bug in OperAnalyzer
[scilab.git] / scilab / modules / ast / src / cpp / analysis / OperAnalyzer.cpp
index 3a60d82..f0d7ca9 100644 (file)
 
 namespace analysis
 {
-    bool OperAnalyzer::analyze(AnalysisVisitor & visitor, ast::Exp & e)
+bool OperAnalyzer::analyze(AnalysisVisitor & visitor, ast::Exp & e)
+{
+    ast::OpExp & oe = static_cast<ast::OpExp &>(e);
+    const ast::OpExp::Oper oper = oe.getOper();
+    if (oper == ast::OpExp::plus || oper == ast::OpExp::minus || oper == ast::OpExp::times)
     {
-        ast::OpExp & oe = static_cast<ast::OpExp &>(e);
-        const ast::OpExp::Oper oper = oe.getOper();
-        if (oper == ast::OpExp::plus || oper == ast::OpExp::minus || oper == ast::OpExp::times)
+        if (ast::MemfillExp * mfe = analyzeMemfill(visitor, oe))
         {
-            if (ast::MemfillExp * mfe = analyzeMemfill(visitor, oe))
-           {
-               mfe->setVerbose(e.isVerbose());
-               e.replace(mfe);
+            mfe->setVerbose(e.isVerbose());
+            e.replace(mfe);
 
-               return true;
-           }
+            return true;
         }
-
-       /*if (ast::ExtendedOpExp * eoe = analyzeMemfill(visitor, oe))
-       {
-           eoe->setVerbose(e.isVerbose());
-           e.replace(eoe);
-           
-           return true;
-           }*/
-       
-       return false;
     }
 
-    /*ast::ExtendedOpExp * OperAnalyzer::analyzeTransposedArgs(ast::OpExp & oe)
-    {
-       ast::Exp & L = oe.getLeft();
-        ast::Exp & R = oe.getRight();
-       ast::ExtendedOpExp::OP Lop, Rop;
-       ast::Exp * Le = &L;
-       ast::Exp * Re = &R;
-
-       if (L.isTransposeExp())
-       {
-           ast::TransposeExp & te = static_cast<ast::TransposeExp &>(L);
-           if (te.getConjugate() == ast::TransposeExp::_Conjugate_)
-           {
-               Lop = ast::ExtendedOpExp::ADJOINT;
-           }
-           else
-           {
-               Lop = ast::ExtendedOpExp::TRANSP;
-           }
-           Le = &te.getExp();
-       }
-
-       if (R.isTransposeExp())
-       {
-           ast::TransposeExp & te = static_cast<ast::TransposeExp &>(R);
-           if (te.getConjugate() == ast::TransposeExp::_Conjugate_)
-           {
-               Rop = ast::ExtendedOpExp::ADJOINT;
-           }
-           else
-           {
-               Rop = ast::ExtendedOpExp::TRANSP;
-           }
-           Re = &te.getExp();
-       }
-
-       if (Lop != ast::ExtendedOpExp::NONE || Rop != ast::ExtendedOpExp::NONE)
-       {
-           return new ast::ExtendedOpExp(oe.getLocation(), *Le, Lop, oe.getOper(), *Re, Rop);
-       }
-
-       return nullptr;
-       }*/
-    
-    ast::MemfillExp * OperAnalyzer::analyzeMemfill(AnalysisVisitor & visitor, ast::OpExp & oe)
-    {
-        const ast::OpExp::Oper oper = oe.getOper();
-        ast::Exp & L = oe.getLeft();
-        ast::Exp & R = oe.getRight();
+    /*if (ast::ExtendedOpExp * eoe = analyzeMemfill(visitor, oe))
+      {
+      eoe->setVerbose(e.isVerbose());
+      e.replace(eoe);
+
+      return true;
+      }*/
+
+    return false;
+}
+
+/*ast::ExtendedOpExp * OperAnalyzer::analyzeTransposedArgs(ast::OpExp & oe)
+  {
+  ast::Exp & L = oe.getLeft();
+  ast::Exp & R = oe.getRight();
+  ast::ExtendedOpExp::OP Lop, Rop;
+  ast::Exp * Le = &L;
+  ast::Exp * Re = &R;
+
+  if (L.isTransposeExp())
+  {
+  ast::TransposeExp & te = static_cast<ast::TransposeExp &>(L);
+  if (te.getConjugate() == ast::TransposeExp::_Conjugate_)
+  {
+  Lop = ast::ExtendedOpExp::ADJOINT;
+  }
+  else
+  {
+  Lop = ast::ExtendedOpExp::TRANSP;
+  }
+  Le = &te.getExp();
+  }
+
+  if (R.isTransposeExp())
+  {
+  ast::TransposeExp & te = static_cast<ast::TransposeExp &>(R);
+  if (te.getConjugate() == ast::TransposeExp::_Conjugate_)
+  {
+  Rop = ast::ExtendedOpExp::ADJOINT;
+  }
+  else
+  {
+  Rop = ast::ExtendedOpExp::TRANSP;
+  }
+  Re = &te.getExp();
+  }
+
+  if (Lop != ast::ExtendedOpExp::NONE || Rop != ast::ExtendedOpExp::NONE)
+  {
+  return new ast::ExtendedOpExp(oe.getLocation(), *Le, Lop, oe.getOper(), *Re, Rop);
+  }
+
+  return nullptr;
+  }*/
+
+ast::MemfillExp * OperAnalyzer::analyzeMemfill(AnalysisVisitor & visitor, ast::OpExp & oe)
+{
+    const ast::OpExp::Oper oper = oe.getOper();
+    ast::Exp & L = oe.getLeft();
+    ast::Exp & R = oe.getRight();
+
+    ast::Exp * constant = nullptr;
+    ast::MemfillExp * me = nullptr;
+    ast::exps_t args;
+    double value;
+    bool callAtLeft;
 
-        ast::Exp * constant = nullptr;
-        ast::exps_t args;
-        double value;
-        bool callAtLeft;
+    // We try to match something like A +* ones(...) or A +* zeros(...)
+    if (L.isCallExp())
+    {
+        ast::CallExp & ce = static_cast<ast::CallExp &>(L);
+        if (ce.getName().isSimpleVar())
+        {
+            const std::wstring & name = static_cast<ast::SimpleVar &>(ce.getName()).getSymbol().getName();
+            if (name == L"ones")
+            {
+                value = 1;
+                args = ce.getArgs();
+                constant = &R;
+                callAtLeft = true;
+            }
+            else if (name == L"zeros")
+            {
+                value = 0;
+                args = ce.getArgs();
+                constant = &R;
+                callAtLeft = true;
+            }
+        }
+    }
 
-        // We try to match something like A +* ones(...) or A +* zeros(...)
-        if (L.isCallExp())
+    if (!constant)
+    {
+        if (R.isCallExp())
         {
-            ast::CallExp & ce = static_cast<ast::CallExp &>(L);
+            ast::CallExp & ce = static_cast<ast::CallExp &>(R);
             if (ce.getName().isSimpleVar())
             {
                 const std::wstring & name = static_cast<ast::SimpleVar &>(ce.getName()).getSymbol().getName();
@@ -110,130 +136,130 @@ namespace analysis
                 {
                     value = 1;
                     args = ce.getArgs();
-                    constant = &R;
-                    callAtLeft = true;
+                    constant = &L;
+                    callAtLeft = false;
                 }
                 else if (name == L"zeros")
                 {
                     value = 0;
                     args = ce.getArgs();
-                    constant = &R;
-                    callAtLeft = true;
+                    constant = &L;
+                    callAtLeft = false;
                 }
             }
         }
+    }
 
-        if (!constant)
+    if (constant && (oper == ast::OpExp::plus || oper == ast::OpExp::minus || oper == ast::OpExp::times))
+    {
+        Result & res = constant->getDecorator().getResult();
+        if (res.getType().ismatrix() && res.getType().isscalar())
         {
-            if (R.isCallExp())
+            TIType ty(visitor.getGVN(), TIType::DOUBLE);
+            ast::exps_t cloneArgs;
+            cloneArgs.reserve(args.size());
+            for (auto arg : args)
             {
-                ast::CallExp & ce = static_cast<ast::CallExp &>(R);
-                if (ce.getName().isSimpleVar())
-                {
-                    const std::wstring & name = static_cast<ast::SimpleVar &>(ce.getName()).getSymbol().getName();
-                    if (name == L"ones")
-                    {
-                        value = 1;
-                        args = ce.getArgs();
-                        constant = &L;
-                        callAtLeft = false;
-                    }
-                    else if (name == L"zeros")
-                    {
-                        value = 0;
-                        args = ce.getArgs();
-                        constant = &L;
-                        callAtLeft = false;
-                    }
-                }
+                ast::Exp * cl = arg->clone();
+                cl->getDecorator().setResult(arg->getDecorator().getResult());
+                cloneArgs.push_back(cl);
             }
-        }
 
-        if (constant)
-        {
-           ast::exps_t cloneArgs;
-           cloneArgs.reserve(args.size());
-           for (auto arg : args)
-           {
-               cloneArgs.push_back(arg->clone());
-           }
-           
             switch (oper)
             {
-            case ast::OpExp::plus :
-            {
-                // plus is commutative so callAtLeft is ignored
-                Result & res = constant->getDecorator().getResult();
-
-                if (res.getType().ismatrix() && res.getType().isscalar())
+                case ast::OpExp::plus :
                 {
+                    // plus is commutative so callAtLeft is ignored
                     // we have something like x + ones(...) => it is a fill with x+1
                     const Location & loc = oe.getLocation();
+                    ast::Exp * valExp;
                     double x;
                     if (res.getConstant().getDblValue(x))
                     {
-                        return new ast::MemfillExp(loc, *new ast::DoubleExp(loc, new types::Double(x + value)), cloneArgs);
+                        valExp = new ast::DoubleExp(loc, new types::Double(x + value));
+                        valExp->getDecorator().setResult(Result(ty));
                     }
                     else
                     {
-                        return new ast::MemfillExp(loc, *new ast::OpExp(loc, *constant->clone(), ast::OpExp::plus, *new ast::DoubleExp(loc, new types::Double(value))), cloneArgs);
+                        ast::Exp * cl = constant->clone();
+                        cl->getDecorator().setResult(constant->getDecorator().getResult());
+                        valExp = new ast::DoubleExp(loc, new types::Double(value));
+                        valExp->getDecorator().setResult(Result(ty));
+                        valExp = new ast::OpExp(loc, *cl, ast::OpExp::plus, *valExp);
+                        valExp->getDecorator().setResult(Result(Checkers::check_____add____(visitor.getGVN(), cl->getDecorator().getResult().getType(), ty)));
                     }
+                    me = new ast::MemfillExp(loc, *valExp, cloneArgs);
+                    break;
                 }
-                break;
-            }
-            case ast::OpExp::minus :
-            {
-                Result & res = constant->getDecorator().getResult();
-
-                if (res.getType().ismatrix() && res.getType().isscalar())
+                case ast::OpExp::minus :
                 {
                     // we have something like x - ones(...) => it is a fill with x-1
                     const Location & loc = oe.getLocation();
+                    ast::Exp * valExp;
                     double x;
                     if (res.getConstant().getDblValue(x))
                     {
-                        return new ast::MemfillExp(loc, *new ast::DoubleExp(loc, new types::Double(callAtLeft ? value - x : x - value)), cloneArgs);
-                    }
-                    else if (callAtLeft)
-                    {
-                        return new ast::MemfillExp(loc, *new ast::OpExp(loc, *new ast::DoubleExp(loc, new types::Double(value)), ast::OpExp::minus, *constant->clone()), cloneArgs);
+                        valExp = new ast::DoubleExp(loc, new types::Double(callAtLeft ? value - x : x - value));
+                        valExp->getDecorator().setResult(Result(ty));
                     }
                     else
                     {
-                        return new ast::MemfillExp(loc, *new ast::OpExp(loc, *constant->clone(), ast::OpExp::minus, *new ast::DoubleExp(loc, new types::Double(value))), cloneArgs);
+                        ast::Exp * cl = constant->clone();
+                        cl->getDecorator().setResult(constant->getDecorator().getResult());
+                        valExp = new ast::DoubleExp(loc, new types::Double(value));
+                        valExp->getDecorator().setResult(Result(ty));
+                        if (callAtLeft)
+                        {
+                            valExp = new ast::OpExp(loc, *valExp, ast::OpExp::minus, *cl);
+                            valExp->getDecorator().setResult(Result(Checkers::check_____sub____(visitor.getGVN(), ty, cl->getDecorator().getResult().getType())));
+                        }
+                        else
+                        {
+                            valExp = new ast::OpExp(loc, *cl, ast::OpExp::minus, *valExp);
+                            valExp->getDecorator().setResult(Result(Checkers::check_____sub____(visitor.getGVN(), cl->getDecorator().getResult().getType(), ty)));
+                        }
                     }
+                    me = new ast::MemfillExp(loc, *valExp, cloneArgs);
+                    break;
                 }
-
-                break;
-            }
-            case ast::OpExp::times :
-            {
-                // times is commutative so callAtLeft is ignored
-                Result & res = constant->getDecorator().getResult();
-
-                if (res.getType().ismatrix() && res.getType().isscalar())
+                case ast::OpExp::times :
                 {
-                    // we have something like x + ones(...) => it is a fill with x+1
+                    // times is commutative so callAtLeft is ignored
+                    // we have something like x * ones(...) => it is a fill with x
                     const Location & loc = oe.getLocation();
-                    double x;
-                    if (res.getConstant().getDblValue(x))
+                    ast::Exp * valExp;
+                    double x = 0;
+                    if (value == 0 || res.getConstant().getDblValue(x))
                     {
-                        return new ast::MemfillExp(loc, *new ast::DoubleExp(loc, new types::Double(x * value)), cloneArgs);
-                    }
-                    else if (value == 0)
-                    {
-                        return new ast::MemfillExp(loc, *new ast::DoubleExp(loc, new types::Double(0)), cloneArgs);
+                        valExp = new ast::DoubleExp(loc, new types::Double(x * value));
+                        valExp->getDecorator().setResult(Result(ty));
                     }
                     else
                     {
-                        return new ast::MemfillExp(loc, *constant->clone(), cloneArgs);
+                        valExp = constant->clone();
+                        valExp->getDecorator().setResult(constant->getDecorator().getResult());
                     }
+                    me = new ast::MemfillExp(loc, *valExp, cloneArgs);
+                    break;
                 }
-                break;
             }
+
+            if (me)
+            {
+                if (callAtLeft)
+                {
+                    ast::CallExp & ce = static_cast<ast::CallExp &>(L);
+                    me->getDecorator().setResult(ce.getDecorator().getResult());
+                }
+                else
+                {
+                    ast::CallExp & ce = static_cast<ast::CallExp &>(R);
+                    me->getDecorator().setResult(ce.getDecorator().getResult());
+                }
             }
         }
-
-        return nullptr;
     }
+
+    return me;
+}
 }