Analysis: fix bug in listexp when in a vardec
[scilab.git] / scilab / modules / ast / src / cpp / analysis / VisitListExp.cpp
index 6d15488..c623f95 100644 (file)
 
 namespace analysis
 {
+
 void AnalysisVisitor::visit(ast::ListExp & e)
 {
-    double start, step, end;
-    if (AnalysisVisitor::asDouble(e.getStart(), start) && AnalysisVisitor::asDouble(e.getStep(), step) && AnalysisVisitor::asDouble(e.getEnd(), end))
+    logger.log(L"ListExp", e.getLocation());
+    if (e.getParent()->isVarDec())
     {
+        visitInVarDecCtxt(e);
+        return;
+    }
+
+    e.getStart().accept(*this);
+    Result & Rstart = e.getStart().getDecorator().getResult();
+    e.getEnd().accept(*this);
+    Result & Rend = e.getEnd().getDecorator().getResult();
+    e.getStep().accept(*this);
+    Result & Rstep = e.getStep().getDecorator().getResult();
+
+    double start = 1;
+    double step = 1;
+    double end = 1;
+    if (Rstart.getConstant().getDblValue(start) && Rstep.getConstant().getDblValue(step) && Rend.getConstant().getDblValue(end))
+    {
+        // Start, Step & End are constant !
         double out;
         int type = ForList64::checkList(start, end, step, out);
 
@@ -39,7 +57,7 @@ void AnalysisVisitor::visit(ast::ListExp & e)
                 {
                     out = start;
                 }
-                e.getDecorator().setResult(Result(T, temp.add(T)));
+                e.getDecorator().setResult(Result(T, dm.getTmpId(T, false)));
                 break;
             }
             default:
@@ -51,25 +69,29 @@ void AnalysisVisitor::visit(ast::ListExp & e)
         return;
     }
 
-    e.getStart().accept(*this);
-    Result Rstart = getResult();
+    if (step == 0 || tools::isNaN(step) || !tools::isFinite(step)
+            || tools::isNaN(start) || !tools::isFinite(start)
+            ||  tools::isNaN(end) || !tools::isFinite(end))
+    {
+        e.getDecorator().setResult(Result(TIType(dm.getGVN(), TIType::EMPTY), -1));
+        return;
+    }
 
-    if (!AnalysisVisitor::asDouble(e.getStep(), step) || (step != -1 && step != 1))
+    if (!Rstep.getConstant().getDblValue(step) || (step != -1 && step != 1))
     {
-        Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false, true), -1));
+        Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
         setResult(res);
         return;
     }
 
-    GVN::Value * gvnStart;
-
-    if (!Rstart.getType().isscalar())
+    if (!Rstart.getType().isscalar() || !Rend.getType().isscalar())
     {
-        Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false, true), -1));
+        Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
         setResult(res);
         return;
     }
 
+    GVN::Value * gvnStart;
     if (Rstart.getConstant().getDblValue(start))
     {
         if (tools::getIntType(start) == tools::NOTANINT)
@@ -86,14 +108,12 @@ void AnalysisVisitor::visit(ast::ListExp & e)
         gvnStart = Rstart.getConstant().getGVNValue();
         if (!gvnStart)
         {
-            Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false, true), -1));
+            Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
             setResult(res);
             return;
         }
     }
 
-    e.getEnd().accept(*this);
-    Result & Rend = getResult();
     GVN::Value * gvnEnd;
 
     if (Rend.getConstant().getDblValue(end))
@@ -112,15 +132,23 @@ void AnalysisVisitor::visit(ast::ListExp & e)
         gvnEnd = Rend.getConstant().getGVNValue();
         if (!gvnEnd)
         {
-            Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false, true), -1));
+            Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
             setResult(res);
             return;
         }
     }
 
-    GVN::Value * ONEValue = getGVN().getValue(1.);
+    GVN::Value * ONEValue = getGVN().getValue(1);
     SymbolicDimension ONE(getGVN(), ONEValue);
     GVN::Value * v;
+
+    if (gvnStart->value == gvnEnd->value)
+    {
+        Result & res = e.getDecorator().setResult(Result(TIType(getGVN(), TIType::DOUBLE, ONE, ONE)));
+        setResult(res);
+        return;
+    }
+
     if (step == 1)
     {
         v = getGVN().getValue(OpValue::Kind::MINUS, *gvnEnd, *gvnStart);
@@ -131,7 +159,7 @@ void AnalysisVisitor::visit(ast::ListExp & e)
     }
     v = getGVN().getValue(OpValue::Kind::PLUS, *v, *ONEValue);
 
-    if (v->poly->isConstant() && v->poly->constant <= 0)
+    if (v->poly->constant < 0 && v->poly->isCoeffNegative(false))
     {
         TIType type(getGVN(), TIType::EMPTY);
         e.getDecorator().res = Result(type);
@@ -146,11 +174,82 @@ void AnalysisVisitor::visit(ast::ListExp & e)
         }
         else
         {
-            Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false, true), -1));
+            Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
             setResult(res);
             return;
         }
     }
+
     setResult(e.getDecorator().res);
 }
+
+void AnalysisVisitor::visitInVarDecCtxt(ast::ListExp & e)
+{
+    e.getStart().accept(*this);
+    Result & Rstart = e.getStart().getDecorator().getResult();
+    e.getEnd().accept(*this);
+    Result & Rend = e.getEnd().getDecorator().getResult();
+    e.getStep().accept(*this);
+    Result & Rstep = e.getStep().getDecorator().getResult();
+
+    double start = 1;
+    double step = 1;
+    double end = 1;
+    if ((Rstart.getConstant().getDblValue(start) || Rstep.getConstant().getDblValue(step)
+            || Rend.getConstant().getDblValue(end)) &&
+            (step == 0 || tools::isNaN(step) || !tools::isFinite(step)
+             || tools::isNaN(start) || !tools::isFinite(start)
+             ||  tools::isNaN(end) || !tools::isFinite(end)))
+    {
+        // We have an invalid list
+        e.getDecorator().setResult(Result(TIType(dm.getGVN(), TIType::EMPTY), -1));
+        return;
+    }
+
+    ast::VarDec & vd = *static_cast<ast::VarDec *>(e.getParent());
+    const symbol::Symbol & sym = vd.getSymbol();
+    GVN::Value * startRange = nullptr;
+    GVN::Value * endRange = nullptr;
+    Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), TIType::DOUBLE), -1));
+
+    if (Rstart.getConstant().getGVNValue(getGVN(), startRange) && Rend.getConstant().getGVNValue(getGVN(), endRange))
+    {
+        // Start & End are GVN values
+        res.setRange(SymbolicRange(getGVN(), startRange, endRange));
+    }
+    else
+    {
+        SymbolicRange & rangeStart = Rstart.getRange();
+        if (rangeStart.isValid())
+        {
+            // Start is an iterator: for i=1:N, for j=i:N, ... in the second for "i" in "i:n" is an iterator
+            if (endRange || Rend.getConstant().getGVNValue(getGVN(), endRange))
+            {
+                // Start is an iterator and End is GVN value
+                res.setRange(SymbolicRange(getGVN(), rangeStart.getStart(), endRange));
+            }
+            else
+            {
+                SymbolicRange & rangeEnd = Rend.getRange();
+                if (rangeEnd.isValid())
+                {
+                    // Start & End are iterators
+                    res.setRange(SymbolicRange(getGVN(), rangeStart.getStart(), rangeEnd.getEnd()));
+                }
+            }
+        }
+        else if (startRange || Rstart.getConstant().getGVNValue(getGVN(), startRange))
+        {
+            // Start is a GVN value
+            SymbolicRange & rangeEnd = Rend.getRange();
+            if (rangeEnd.isValid())
+            {
+                // Start is a GVN value and End is an iterator
+                res.setRange(SymbolicRange(getGVN(), startRange, rangeEnd.getEnd()));
+            }
+        }
+    }
+
+    setResult(res);
+}
 }