Analysis: fix bugs & add a loop analyzer 72/17172/2
Calixte DENIZET [Tue, 8 Sep 2015 11:51:14 +0000 (13:51 +0200)]
Change-Id: Iefe5e7075e8c1013fec3372d9b38475db0224073

59 files changed:
scilab/modules/ast/Makefile.am
scilab/modules/ast/Makefile.in
scilab/modules/ast/ast.vcxproj
scilab/modules/ast/ast.vcxproj.filters
scilab/modules/ast/includes/analysis/AnalysisVisitor.hxx
scilab/modules/ast/includes/analysis/Decorator.hxx
scilab/modules/ast/includes/analysis/OptionalDecoration.hxx [new file with mode: 0644]
scilab/modules/ast/includes/analysis/TIType.hxx
scilab/modules/ast/includes/analysis/checkers/Checkers.hxx
scilab/modules/ast/includes/analysis/data/Block.hxx
scilab/modules/ast/includes/analysis/data/Clone.hxx [new file with mode: 0644]
scilab/modules/ast/includes/analysis/data/Data.hxx
scilab/modules/ast/includes/analysis/data/DataManager.hxx
scilab/modules/ast/includes/analysis/data/FunctionBlock.hxx
scilab/modules/ast/includes/analysis/data/GlobalsCollector.hxx
scilab/modules/ast/includes/analysis/data/LoopAnalyzer.hxx [new file with mode: 0644]
scilab/modules/ast/includes/analysis/data/LoopBlock.hxx
scilab/modules/ast/includes/analysis/data/MacroDef.hxx
scilab/modules/ast/includes/analysis/tools.hxx
scilab/modules/ast/includes/exps/ast.hxx
scilab/modules/ast/includes/exps/mapintselectexp.hxx
scilab/modules/ast/includes/exps/smallintselectexp.hxx
scilab/modules/ast/src/cpp/analysis/Block.cpp
scilab/modules/ast/src/cpp/analysis/CeilAnalyzer.cpp
scilab/modules/ast/src/cpp/analysis/Checkers.cpp
scilab/modules/ast/src/cpp/analysis/CompleteMacroSignature.cpp
scilab/modules/ast/src/cpp/analysis/ConstantVisitor.cpp
scilab/modules/ast/src/cpp/analysis/DataManager.cpp
scilab/modules/ast/src/cpp/analysis/FunctionBlock.cpp
scilab/modules/ast/src/cpp/analysis/GlobalsCollector.cpp
scilab/modules/ast/src/cpp/analysis/LoopBlock.cpp
scilab/modules/ast/src/cpp/analysis/PolymorphicMacroCache.cpp
scilab/modules/ast/src/cpp/analysis/VisitAssignExp.cpp
scilab/modules/ast/src/cpp/analysis/VisitIfExp.cpp
scilab/modules/ast/src/cpp/analysis/VisitListExp.cpp
scilab/modules/ast/src/cpp/analysis/VisitSelectExp.cpp
scilab/modules/ast/src/cpp/analysis/check_____add____.cpp
scilab/modules/ast/src/cpp/analysis/check_____and____.cpp
scilab/modules/ast/src/cpp/analysis/check_____andand____.cpp
scilab/modules/ast/src/cpp/analysis/check_____dotpower____.cpp
scilab/modules/ast/src/cpp/analysis/check_____dotrdiv____.cpp
scilab/modules/ast/src/cpp/analysis/check_____dottimes____.cpp
scilab/modules/ast/src/cpp/analysis/check_____eq____.cpp
scilab/modules/ast/src/cpp/analysis/check_____ge____.cpp
scilab/modules/ast/src/cpp/analysis/check_____gt____.cpp
scilab/modules/ast/src/cpp/analysis/check_____krontimes____.cpp
scilab/modules/ast/src/cpp/analysis/check_____ldivide____.cpp
scilab/modules/ast/src/cpp/analysis/check_____le____.cpp
scilab/modules/ast/src/cpp/analysis/check_____lt____.cpp
scilab/modules/ast/src/cpp/analysis/check_____neq____.cpp
scilab/modules/ast/src/cpp/analysis/check_____not____.cpp
scilab/modules/ast/src/cpp/analysis/check_____or____.cpp
scilab/modules/ast/src/cpp/analysis/check_____oror____.cpp
scilab/modules/ast/src/cpp/analysis/check_____power____.cpp
scilab/modules/ast/src/cpp/analysis/check_____rdivide____.cpp
scilab/modules/ast/src/cpp/analysis/check_____sub____.cpp
scilab/modules/ast/src/cpp/analysis/check_____times____.cpp
scilab/modules/ast/src/cpp/analysis/check_atan.cpp
scilab/modules/ast/src/cpp/analysis/check_sign.cpp [new file with mode: 0644]

index 747d83d..f854a94 100644 (file)
@@ -213,6 +213,7 @@ src/cpp/analysis/check_____sub____.cpp\
 src/cpp/analysis/check_sinh.cpp\
 src/cpp/analysis/check_toc.cpp\
 src/cpp/analysis/check_isscalar.cpp\
+src/cpp/analysis/check_sign.cpp\
 src/cpp/analysis/check_int8.cpp\
 src/cpp/analysis/check_____rdivide____.cpp\
 src/cpp/analysis/check_matrix.cpp\
index 1c839bf..a06fba0 100644 (file)
@@ -333,6 +333,7 @@ am__libsciast_la_SOURCES_DIST = src/c/operations/doublecomplex.c \
        src/cpp/analysis/check_____sub____.cpp \
        src/cpp/analysis/check_sinh.cpp src/cpp/analysis/check_toc.cpp \
        src/cpp/analysis/check_isscalar.cpp \
+       src/cpp/analysis/check_sign.cpp \
        src/cpp/analysis/check_int8.cpp \
        src/cpp/analysis/check_____rdivide____.cpp \
        src/cpp/analysis/check_matrix.cpp \
@@ -556,6 +557,7 @@ am_libsciast_la_OBJECTS =  \
        src/cpp/analysis/libsciast_la-check_sinh.lo \
        src/cpp/analysis/libsciast_la-check_toc.lo \
        src/cpp/analysis/libsciast_la-check_isscalar.lo \
+       src/cpp/analysis/libsciast_la-check_sign.lo \
        src/cpp/analysis/libsciast_la-check_int8.lo \
        src/cpp/analysis/libsciast_la-check_____rdivide____.lo \
        src/cpp/analysis/libsciast_la-check_matrix.lo \
@@ -946,6 +948,7 @@ pdfdir = @pdfdir@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
 psdir = @psdir@
+runstatedir = @runstatedir@
 sbindir = @sbindir@
 sharedstatedir = @sharedstatedir@
 srcdir = @srcdir@
@@ -1115,6 +1118,7 @@ libsciast_la_SOURCES = src/c/operations/doublecomplex.c \
        src/cpp/analysis/check_____sub____.cpp \
        src/cpp/analysis/check_sinh.cpp src/cpp/analysis/check_toc.cpp \
        src/cpp/analysis/check_isscalar.cpp \
+       src/cpp/analysis/check_sign.cpp \
        src/cpp/analysis/check_int8.cpp \
        src/cpp/analysis/check_____rdivide____.cpp \
        src/cpp/analysis/check_matrix.cpp \
@@ -2142,6 +2146,9 @@ src/cpp/analysis/libsciast_la-check_toc.lo:  \
 src/cpp/analysis/libsciast_la-check_isscalar.lo:  \
        src/cpp/analysis/$(am__dirstamp) \
        src/cpp/analysis/$(DEPDIR)/$(am__dirstamp)
+src/cpp/analysis/libsciast_la-check_sign.lo:  \
+       src/cpp/analysis/$(am__dirstamp) \
+       src/cpp/analysis/$(DEPDIR)/$(am__dirstamp)
 src/cpp/analysis/libsciast_la-check_int8.lo:  \
        src/cpp/analysis/$(am__dirstamp) \
        src/cpp/analysis/$(DEPDIR)/$(am__dirstamp)
@@ -2360,6 +2367,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@src/cpp/analysis/$(DEPDIR)/libsciast_la-check_prod.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/cpp/analysis/$(DEPDIR)/libsciast_la-check_rand.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/cpp/analysis/$(DEPDIR)/libsciast_la-check_round.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/cpp/analysis/$(DEPDIR)/libsciast_la-check_sign.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/cpp/analysis/$(DEPDIR)/libsciast_la-check_sin.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/cpp/analysis/$(DEPDIR)/libsciast_la-check_sinh.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/cpp/analysis/$(DEPDIR)/libsciast_la-check_sinm.Plo@am__quote@
@@ -3901,6 +3909,13 @@ src/cpp/analysis/libsciast_la-check_isscalar.lo: src/cpp/analysis/check_isscalar
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsciast_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/cpp/analysis/libsciast_la-check_isscalar.lo `test -f 'src/cpp/analysis/check_isscalar.cpp' || echo '$(srcdir)/'`src/cpp/analysis/check_isscalar.cpp
 
+src/cpp/analysis/libsciast_la-check_sign.lo: src/cpp/analysis/check_sign.cpp
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsciast_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/cpp/analysis/libsciast_la-check_sign.lo -MD -MP -MF src/cpp/analysis/$(DEPDIR)/libsciast_la-check_sign.Tpo -c -o src/cpp/analysis/libsciast_la-check_sign.lo `test -f 'src/cpp/analysis/check_sign.cpp' || echo '$(srcdir)/'`src/cpp/analysis/check_sign.cpp
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) src/cpp/analysis/$(DEPDIR)/libsciast_la-check_sign.Tpo src/cpp/analysis/$(DEPDIR)/libsciast_la-check_sign.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='src/cpp/analysis/check_sign.cpp' object='src/cpp/analysis/libsciast_la-check_sign.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsciast_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/cpp/analysis/libsciast_la-check_sign.lo `test -f 'src/cpp/analysis/check_sign.cpp' || echo '$(srcdir)/'`src/cpp/analysis/check_sign.cpp
+
 src/cpp/analysis/libsciast_la-check_int8.lo: src/cpp/analysis/check_int8.cpp
 @am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsciast_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/cpp/analysis/libsciast_la-check_int8.lo -MD -MP -MF src/cpp/analysis/$(DEPDIR)/libsciast_la-check_int8.Tpo -c -o src/cpp/analysis/libsciast_la-check_int8.lo `test -f 'src/cpp/analysis/check_int8.cpp' || echo '$(srcdir)/'`src/cpp/analysis/check_int8.cpp
 @am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) src/cpp/analysis/$(DEPDIR)/libsciast_la-check_int8.Tpo src/cpp/analysis/$(DEPDIR)/libsciast_la-check_int8.Plo
index cbc49f3..fd4d713 100644 (file)
@@ -284,12 +284,14 @@ lib /DEF:"$(ProjectDir)string_import.def" /SUBSYSTEM:WINDOWS /MACHINE:$(Platform
     <ClInclude Include="includes\analysis\ConstantValue.hxx" />
     <ClInclude Include="includes\analysis\ConstantVisitor.hxx" />
     <ClInclude Include="includes\analysis\data\Block.hxx" />
+    <ClInclude Include="includes\analysis\data\Clone.hxx" />
     <ClInclude Include="includes\analysis\data\CompleteMacroSignature.hxx" />
     <ClInclude Include="includes\analysis\data\Data.hxx" />
     <ClInclude Include="includes\analysis\data\DataManager.hxx" />
     <ClInclude Include="includes\analysis\data\FunctionBlock.hxx" />
     <ClInclude Include="includes\analysis\data\GlobalsCollector.hxx" />
     <ClInclude Include="includes\analysis\data\Info.hxx" />
+    <ClInclude Include="includes\analysis\data\LoopAnalyzer.hxx" />
     <ClInclude Include="includes\analysis\data\LoopBlock.hxx" />
     <ClInclude Include="includes\analysis\data\MacroDef.hxx" />
     <ClInclude Include="includes\analysis\data\MacroInfo.hxx" />
@@ -316,6 +318,7 @@ lib /DEF:"$(ProjectDir)string_import.def" /SUBSYSTEM:WINDOWS /MACHINE:$(Platform
     <ClInclude Include="includes\analysis\gvn\TestGVNVisitor.hxx" />
     <ClInclude Include="includes\analysis\gvn\VarExp.hxx" />
     <ClInclude Include="includes\analysis\logging\Logger.hxx" />
+    <ClInclude Include="includes\analysis\OptionalDecoration.hxx" />
     <ClInclude Include="includes\analysis\positivity\PositivityVisitor.hxx" />
     <ClInclude Include="includes\analysis\Result.hxx" />
     <ClInclude Include="includes\analysis\TIType.hxx" />
@@ -540,6 +543,7 @@ lib /DEF:"$(ProjectDir)string_import.def" /SUBSYSTEM:WINDOWS /MACHINE:$(Platform
     <ClCompile Include="src\cpp\analysis\check_prod.cpp" />
     <ClCompile Include="src\cpp\analysis\check_rand.cpp" />
     <ClCompile Include="src\cpp\analysis\check_round.cpp" />
+    <ClCompile Include="src\cpp\analysis\check_sign.cpp" />
     <ClCompile Include="src\cpp\analysis\check_sin.cpp" />
     <ClCompile Include="src\cpp\analysis\check_sinh.cpp" />
     <ClCompile Include="src\cpp\analysis\check_sinm.cpp" />
index 8f16bff..89e3a4c 100644 (file)
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
     <Library Include="..\..\bin\blasplus.lib" />
     <ClInclude Include="includes\analysis\tools.hxx">
       <Filter>Header Files\analysis</Filter>
     </ClInclude>
+    <ClInclude Include="includes\analysis\OptionalDecoration.hxx">
+      <Filter>Header Files\analysis</Filter>
+    </ClInclude>
+    <ClInclude Include="includes\analysis\data\Clone.hxx">
+      <Filter>Header Files\analysis\data</Filter>
+    </ClInclude>
+    <ClInclude Include="includes\analysis\data\LoopAnalyzer.hxx">
+      <Filter>Header Files\analysis\data</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="src\cpp\ast\debugvisitor.cpp">
     <ClCompile Include="src\cpp\analysis\VarExp.cpp">
       <Filter>Source Files\analysis</Filter>
     </ClCompile>
+    <ClCompile Include="src\cpp\analysis\check_sign.cpp">
+      <Filter>Source Files\analysis</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>
\ No newline at end of file
index ee33900..a9c13d6 100644 (file)
@@ -17,6 +17,7 @@
 #include <limits>
 #include <map>
 #include <memory>
+#include <stack>
 #include <vector>
 
 #include "visitor.hxx"
@@ -64,6 +65,7 @@ private:
     std::vector<Result> multipleLHS;
     logging::Logger logger;
     std::vector<FBlockEmittedListener *> fblockListeners;
+    std::stack<ast::Exp *> loops;
 
     static MapSymCall symscall;
     static MapSymCall initCalls();
@@ -190,6 +192,16 @@ public:
         }
     }
 
+    inline ast::Exp * getCurrentLoop() const
+    {
+        if (!loops.empty())
+        {
+            return loops.top();
+        }
+
+        return nullptr;
+    }
+
     inline void registerFBlockEmittedListener(FBlockEmittedListener * listener)
     {
         if (listener)
@@ -413,9 +425,18 @@ private:
             cv.getExec().setResult(nullptr);
         }
         types::Double * pDbl = static_cast<types::Double *>(e.getConstant());
-        Result & res = e.getDecorator().setResult(TIType(dm.getGVN(), TIType::DOUBLE, pDbl->getRows(), pDbl->getCols()));
-        res.getConstant() = e.getConstant();
-        setResult(res);
+        if (pDbl->isComplex())
+        {
+            Result & res = e.getDecorator().setResult(TIType(dm.getGVN(), TIType::COMPLEX, pDbl->getRows(), pDbl->getCols()));
+            res.getConstant() = e.getConstant();
+            setResult(res);
+        }
+        else
+        {
+            Result & res = e.getDecorator().setResult(TIType(dm.getGVN(), TIType::DOUBLE, pDbl->getRows(), pDbl->getCols()));
+            res.getConstant() = e.getConstant();
+            setResult(res);
+        }
     }
 
     void visit(ast::BoolExp & e)
@@ -510,32 +531,41 @@ private:
     void visit(ast::WhileExp & e)
     {
         logger.log(L"WhileExp", e.getLocation());
+        loops.push(&e);
         e.getTest().accept(*this);
+        dm.releaseTmp(getResult().getTempId());
         e.getBody().accept(*this);
+        loops.pop();
     }
 
     void visit(ast::ForExp & e)
     {
-        // TODO: pb de propagation de constante ds le corps du loop
-        // b = 0; for....; b=b+..; end => le 2nd "b" est replaced by 0
-
         logger.log(L"ForExp", e.getLocation());
+        loops.push(&e);
+
         dm.addBlock(Block::LOOP, &e);
         e.getVardec().accept(*this);
         dm.addBlock(Block::NORMAL, &e.getBody());
         e.getBody().accept(*this);
 
-        if (false && dm.requiresAnotherTrip())
+        if (dm.requiresAnotherTrip())
         {
             std::wcerr << "Invalid forexp: types or refcount are not the same before and after the loop" << std::endl;
 
             dm.finalizeBlock();
             dm.addBlock(Block::NORMAL, &e.getBody());
             e.getBody().accept(*this);
+
+            if (dm.requiresAnotherTrip())
+            {
+                std::wcerr << "Invalid forexp: types or refcount are not the same before and after the loop" << std::endl;
+            }
         }
 
         dm.finalizeBlock();
         dm.finalizeBlock();
+
+        loops.pop();
     }
 
     void visit(ast::BreakExp & e)
@@ -591,20 +621,42 @@ private:
     void visit(ast::SeqExp & e)
     {
         logger.log(L"SeqExp", e.getLocation());
-        for (const auto exp : e.getExps())
+        ast::exps_t::const_iterator i = e.getExps().begin();
+        ast::exps_t::const_iterator end = e.getExps().end();
+        for (; i != end; ++i)
         {
+            ast::Exp * exp = *i;
             if (exp->isCallExp())
             {
                 visit(*static_cast<ast::CallExp *>(exp), /* LHS */ 0);
             }
+            else if (exp->isBreakExp() || exp->isContinueExp())
+            {
+                exp->accept(*this);
+                if (loops.empty())
+                {
+                    // We are not in a loop so this break is useless.
+                    exp->replace(new ast::CommentExp(exp->getLocation(), new std::wstring(L"useless break or continue")));
+                }
+                else
+                {
+                    // We are in a loop: all the code after the break in this SeqExp is useless
+                    break;
+                }
+            }
             else
             {
                 exp->accept(*this);
             }
         }
-        if (!e.getParent())
+
+        if (i != end)
         {
-            //e.accept(dv);
+            ++i;
+            if (i != end)
+            {
+                e.getExps().erase(i, end);
+            }
         }
     }
 
index cff367d..142c5b9 100644 (file)
@@ -13,8 +13,8 @@
 #ifndef __DECORATOR_HXX__
 #define __DECORATOR_HXX__
 
-#include "call/Call.hxx"
 #include "Result.hxx"
+#include "OptionalDecoration.hxx"
 
 #include <iostream>
 
@@ -24,52 +24,76 @@ namespace analysis
 struct Decorator
 {
     Result res;
-    Call * call;
+    OptionalDecoration opt;
     bool cloneData;
     bool deleteData;
     bool hasRefCount;
     bool safe;
 
-    Decorator() : res(), call(nullptr), cloneData(false), deleteData(false), hasRefCount(false), safe(false) { }
+    Decorator() : res(), opt(), cloneData(false), deleteData(false), hasRefCount(false), safe(false) { }
 
     ~Decorator()
     {
-        delete call;
     }
 
     inline Call * getCall() const
     {
-        return call;
+        return opt.get<Call>();
     }
 
     inline Call & setCall(Call * _call)
     {
-        delete call;
-        call = _call;
-        return *call;
+        opt.set(_call);
+        return *_call;
     }
 
     inline Call & setCall(const std::wstring & name)
     {
-        delete call;
-        call = new Call(name);
+        Call * call = new Call(name);
+        opt.set(call);
         return *call;
     }
 
     inline Call & setCall(const std::wstring & name, const std::vector<TIType> & args)
     {
-        delete call;
-        call = new Call(name, args);
+        Call * call = new Call(name, args);
+        opt.set(call);
         return *call;
     }
 
     inline Call & setCall(const std::wstring & name, const TIType & arg)
     {
-        delete call;
-        call = new Call(name, arg);
+        Call * call = new Call(name, arg);
+        opt.set(call);
         return *call;
     }
 
+    inline Clone * getClone() const
+    {
+        return opt.get<Clone>();
+    }
+
+    inline Clone & setClone(Clone * _clone)
+    {
+        opt.set(_clone);
+        return *_clone;
+    }
+
+    inline Clone & addClone(const symbol::Symbol & sym)
+    {
+        Clone * clone = opt.get<Clone>();
+        if (clone)
+        {
+            clone->add(sym);
+        }
+        else
+        {
+            clone = new Clone(sym);
+            opt.set(clone);
+        }
+        return *clone;
+    }
+
     inline Result & setResult(Result && _res)
     {
         res = _res;
@@ -89,9 +113,9 @@ struct Decorator
     friend std::wostream & operator<<(std::wostream & out, const Decorator & deco)
     {
         out << deco.res;
-        if (deco.call)
+        if (!deco.opt.empty())
         {
-            out << L", " << (*deco.call);
+            out << L", " << deco.opt;
         }
         out << L", Cl:" << (deco.cloneData ? L"T" : L"F")
             << L", Del:" << (deco.deleteData ? L"T" : L"F")
diff --git a/scilab/modules/ast/includes/analysis/OptionalDecoration.hxx b/scilab/modules/ast/includes/analysis/OptionalDecoration.hxx
new file mode 100644 (file)
index 0000000..6879692
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+ *  Copyright (C) 2015 - Scilab Enterprises - Calixte DENIZET
+ *
+ *  This file must be used under the terms of the CeCILL.
+ *  This source file is licensed as described in the file COPYING, which
+ *  you should have received as part of this distribution.  The terms
+ *  are also available at
+ *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
+ *
+ */
+
+#ifndef __OPTIONAL_DECORATION_HXX__
+#define __OPTIONAL_DECORATION_HXX__
+
+#include <iostream>
+
+#include "call/Call.hxx"
+#include "data/Clone.hxx"
+
+namespace analysis
+{
+
+class OptionalDecoration
+{
+    enum Type { NONE, CALL, CLONE };
+
+    Type ty;
+    void * ptr;
+
+public:
+
+    OptionalDecoration() : ty(NONE), ptr(nullptr) { }
+    OptionalDecoration(Call * _ptr) : ty(CALL), ptr(_ptr) { }
+    OptionalDecoration(Clone * _ptr) : ty(CLONE), ptr(_ptr) { }
+    OptionalDecoration(OptionalDecoration && od) : ty(od.ty), ptr(od.ptr)
+    {
+        od.ty = NONE;
+        od.ptr = nullptr;
+    }
+
+    OptionalDecoration(const OptionalDecoration & od) = delete;
+
+    ~OptionalDecoration()
+    {
+        clean();
+    }
+
+    inline bool empty() const
+    {
+        return ty == NONE;
+    }
+
+    template<typename T>
+    inline T * get() const
+    {
+        return static_cast<T *>(ptr);
+    }
+
+    inline void set(Call * _ptr)
+    {
+        clean();
+        ty = CALL;
+        ptr = _ptr;
+    }
+
+    inline void set(Clone * _ptr)
+    {
+        clean();
+        ty = CLONE;
+        ptr = _ptr;
+    }
+
+    friend std::wostream & operator<<(std::wostream & out, const OptionalDecoration & od)
+    {
+        switch (od.ty)
+        {
+            case CALL:
+                out << *od.get<Call>();
+                break;
+            case CLONE:
+                out << *od.get<Clone>();
+                break;
+            default:
+                break;
+        }
+
+        return out;
+    }
+
+private:
+
+    inline void clean()
+    {
+        switch (ty)
+        {
+            case CALL:
+                delete get<Call>();
+                break;
+            case CLONE:
+                delete get<Clone>();
+                break;
+            default:
+                break;
+        }
+    }
+
+};
+
+} // namespace analysis
+
+
+#endif // __OPTIONAL_DECORATION_HXX__
index 3a3e15d..88281b8 100644 (file)
 
 namespace analysis
 {
-    struct TIType
-    {
-        static const std::wstring _boolean_, _ce_, _constant_, _fptr_, _function_, _int16_, _int32_, _int64_, _int8_, _library_, _list_, _mlist_, _polynomial_, _sparse_, _st_, _string_, _tlist_, _uint16_, _uint32_, _uint64_, _uint8_, _unknown_;
-        
-        enum Type { EMPTY = 0, BOOLEAN, COMPLEX, CELL, DOUBLE, FUNCTION, INT16, INT32, INT64, INT8, LIST, LIBRARY, MACRO, MACROFILE, MLIST, POLYNOMIAL, STRING, SPARSE, STRUCT, TLIST, UNKNOWN, UINT16, UINT32, UINT64, UINT8, COUNT };
-        Type type;
-       SymbolicDimension rows;
-       SymbolicDimension cols;
-        bool scalar;
-
-       TIType(const Type _type = UNKNOWN) : type(_type), scalar(true) { }
-        TIType(GVN & gvn) : type(UNKNOWN), rows(gvn, 0.), cols(gvn, 0.), scalar(false) { }
-        TIType(GVN & gvn, const Type _type) : type(_type), rows(gvn, _type == EMPTY ? 0 : 1), cols(gvn, _type == EMPTY ? 0 : 1), scalar(_type != EMPTY) { }
-       TIType(GVN & gvn, const Type _type, const int _rows, const int _cols) : type(_type), rows(gvn, _rows), cols(gvn, _cols), scalar(_rows == 1 && _cols == 1) { }
-       TIType(GVN & gvn, Type _type, const SymbolicDimension & _rows, const SymbolicDimension & _cols) : type(_type), rows(_rows), cols(_cols), scalar(_rows == 1 && _cols == 1) { }
-       TIType(GVN & gvn, const Type _type, const bool _scalar) : type(_type), rows(gvn, _scalar ? 1. : -1.), cols(gvn, _scalar ? 1. : -1.), scalar(_scalar) { }
-
-       inline bool hasValidDims() const
-       {
-           return rows != -2 && cols != -2;
-       }
-
-       inline bool hasInvalidDims() const
-       {
-           return rows == -2;
-       }
-
-       inline TIType asUnknownMatrix()
-       {
-           return TIType(*rows.getGVN(), type, false);
-       }
-
-        inline bool isscalar() const
-        {
-            return scalar;
-        }
+struct TIType
+{
+    static const std::wstring _boolean_, _ce_, _constant_, _fptr_, _function_, _int16_, _int32_, _int64_, _int8_, _library_, _list_, _mlist_, _polynomial_, _sparse_, _st_, _string_, _tlist_, _uint16_, _uint32_, _uint64_, _uint8_, _unknown_;
+
+    enum Type { EMPTY = 0, BOOLEAN, COMPLEX, CELL, DOUBLE, FUNCTION, INT16, INT32, INT64, INT8, LIST, LIBRARY, MACRO, MACROFILE, MLIST, POLYNOMIAL, STRING, SPARSE, STRUCT, TLIST, UNKNOWN, UINT16, UINT32, UINT64, UINT8, COUNT };
+    Type type;
+    SymbolicDimension rows;
+    SymbolicDimension cols;
+    bool scalar;
+
+    TIType(const Type _type = UNKNOWN) : type(_type), scalar(true) { }
+    TIType(GVN & gvn) : type(UNKNOWN), rows(gvn, 0.), cols(gvn, 0.), scalar(false) { }
+    TIType(GVN & gvn, const Type _type) : type(_type), rows(gvn, _type == EMPTY ? 0 : 1), cols(gvn, _type == EMPTY ? 0 : 1), scalar(_type != EMPTY) { }
+    TIType(GVN & gvn, const Type _type, const int _rows, const int _cols) : type(_type), rows(gvn, _rows), cols(gvn, _cols), scalar(_rows == 1 && _cols == 1) { }
+    TIType(GVN & gvn, Type _type, const SymbolicDimension & _rows, const SymbolicDimension & _cols) : type(_type), rows(_rows), cols(_cols), scalar(_rows == 1 && _cols == 1) { }
+    TIType(GVN & gvn, const Type _type, const bool _scalar) : type(_type), rows(gvn, _scalar ? 1. : -1.), cols(gvn, _scalar ? 1. : -1.), scalar(_scalar) { }
+
+    inline bool hasValidDims() const
+    {
+        return rows != -2 && cols != -2;
+    }
 
-        inline void invalidScalar()
-        {
-            scalar = rows == 1 && cols == 1;
-        }
+    inline bool hasInvalidDims() const
+    {
+        return rows == -2;
+    }
 
-        inline bool iscomplex() const
-        {
-            return type == COMPLEX;
-        }
+    inline TIType asUnknownMatrix()
+    {
+        return TIType(*rows.getGVN(), type, false);
+    }
 
-        inline bool isreal() const
-        {
-            return type == DOUBLE;
-        }
+    inline bool isscalar() const
+    {
+        return scalar;
+    }
 
-        inline bool isintegral() const
-        {
-            return type == BOOLEAN || type == INT8 || type == INT16 || type == INT32 || type == INT64 || type == UINT8 || type == UINT16 || type == UINT32 || type == UINT64;
-        }
+    inline void invalidScalar()
+    {
+        scalar = rows == 1 && cols == 1;
+    }
 
-        inline bool ismatrix() const
-        {
-            return type != CELL && type != FUNCTION && type != LIST && type != LIBRARY && type != MACRO && type != MACROFILE && type != MLIST && type != STRUCT && type != TLIST && type != UNKNOWN;
-        }
+    inline bool iscomplex() const
+    {
+        return type == COMPLEX;
+    }
 
-        inline bool issigned() const
-        {
-            return type != UINT8 && type != UINT16 && type != UINT32 && type != UINT64;
-        }
+    inline bool isreal() const
+    {
+        return type == DOUBLE;
+    }
 
-       inline bool isfloating() const
-       {
-           return type == DOUBLE || type == COMPLEX;
-       }
+    inline bool isintegral() const
+    {
+        return type == BOOLEAN || type == INT8 || type == INT16 || type == INT32 || type == INT64 || type == UINT8 || type == UINT16 || type == UINT32 || type == UINT64;
+    }
 
-        inline bool isKnownDims() const
-        {
-            return rows.isValid() && cols.isValid();
-        }
+    inline bool ismatrix() const
+    {
+        return type != CELL && type != FUNCTION && type != LIST && type != LIBRARY && type != MACRO && type != MACROFILE && type != MLIST && type != STRUCT && type != TLIST && type != UNKNOWN;
+    }
 
-        inline bool isUnknownDims() const
-        {
-            return !isKnownDims();
-        }
+    inline bool issigned() const
+    {
+        return type != UINT8 && type != UINT16 && type != UINT32 && type != UINT64;
+    }
 
-        inline bool isknown() const
-        {
-            return type != UNKNOWN;
-        }
+    inline bool isfloating() const
+    {
+        return type == DOUBLE || type == COMPLEX;
+    }
 
-        inline bool isunknown() const
-        {
-            return type == UNKNOWN;
-        }
+    inline bool isKnownDims() const
+    {
+        return rows.isValid() && cols.isValid();
+    }
 
-        inline bool isConstantDims() const
-        {
-            return rows.isConstant() && cols.isConstant();
-        }
+    inline bool isUnknownDims() const
+    {
+        return !isKnownDims();
+    }
 
-        inline void swapDims()
-        {
-            GVN::Value * r = rows.getValue();
-            rows.setValue(cols.getValue());
-            cols.setValue(r);
-        }
+    inline bool isknown() const
+    {
+        return type != UNKNOWN;
+    }
 
-       inline std::size_t hashPureType() const
-       {
-            return isscalar() ? type : (type + TIType::COUNT + 1);
-       }
+    inline bool isunknown() const
+    {
+        return type == UNKNOWN;
+    }
 
-        inline bool operator==(const TIType & r) const
+    inline bool isConstantDims() const
+    {
+        return rows.isConstant() && cols.isConstant();
+    }
+
+    inline void swapDims()
+    {
+        GVN::Value * r = rows.getValue();
+        rows.setValue(cols.getValue());
+        cols.setValue(r);
+    }
+
+    inline std::size_t hashPureType() const
+    {
+        return isscalar() ? type : (type + TIType::COUNT + 1);
+    }
+
+    inline bool operator==(const TIType & r) const
+    {
+        return type == r.type && scalar == r.scalar && rows == r.rows && cols == r.cols;
+    }
+
+    inline bool operator!=(const TIType & r) const
+    {
+        return !(*this == r);
+    }
+
+    inline void merge(const TIType & type)
+    {
+        if (this->type == DOUBLE && type.type == COMPLEX)
         {
-            return type == r.type && scalar == r.scalar && rows == r.rows && cols == r.cols;
+            this->type = COMPLEX;
         }
-
-        inline bool operator!=(const TIType & r) const
+        else if ((this->type != COMPLEX || type.type != DOUBLE) && this->type != type.type)
         {
-            return !(*this == r);
+            this->type = UNKNOWN;
+            rows.setValue(0.);
+            cols.setValue(0.);
         }
-
-       inline void merge(const TIType & type)
+        else if ((!scalar || !type.scalar) && (rows != type.rows || cols != type.cols))
         {
-            if (this->type == DOUBLE && type.type == COMPLEX)
+            if (rows != type.rows)
             {
-               this->type = COMPLEX;
+                rows.setValue(rows.getGVN()->getValue());
             }
-           else if ((this->type != COMPLEX || type.type != DOUBLE) && this->type != type.type) 
-           {
-               this->type = UNKNOWN;
-               rows.setValue(0.);
-               cols.setValue(0.);
-           }
-           else if ((!scalar || !type.scalar) && (rows != type.rows || cols != type.cols))
-           {
-               if (rows != type.rows)
-               {
-                   rows.setValue(rows.getGVN()->getValue());
-               }
-               if (cols != type.cols)
-               {
-                   cols.setValue(cols.getGVN()->getValue());
-               }
-               scalar = false;
-           }
-           /*else if ((!scalar || !type.scalar) && (rows != type.rows || cols != type.cols))
-           {
-               rows.invalid();
-               cols.invalid();
-               scalar = false;
-           }*/
-       }
-
-       template<typename> static Type getTI();
-
-        inline std::string get_mangling() const
-        {
-            const bool kd = isKnownDims();
-            switch (type)
+            if (cols != type.cols)
             {
+                cols.setValue(cols.getGVN()->getValue());
+            }
+            scalar = false;
+        }
+        /*else if ((!scalar || !type.scalar) && (rows != type.rows || cols != type.cols))
+        {
+        rows.invalid();
+        cols.invalid();
+        scalar = false;
+        }*/
+    }
+
+    template<typename> static Type getTI();
+
+    inline std::string get_mangling() const
+    {
+        const bool kd = isKnownDims();
+        switch (type)
+        {
             case EMPTY :
                 return "E";
             case BOOLEAN :
-                return kd ? (scalar ? "S_b" : "M_b") : "U_b";
+                return kd ? (scalar ? "Sb" : "Mb") : "Ub";
             case COMPLEX :
-                return kd ? (scalar ? "S_c" : "M_c") : "U_c";
+                return kd ? (scalar ? "Sc" : "Mc") : "Uc";
             case CELL :
-                return kd ? (scalar ? "S_ce" : "M_ce") : "U_ce";
+                return kd ? (scalar ? "Sce" : "Mce") : "Uce";
             case DOUBLE :
-                return kd ? (scalar ? "S_d" : "M_d") : "U_d";
+                return kd ? (scalar ? "Sd" : "Md") : "Ud";
             case FUNCTION :
-                return kd ? (scalar ? "S_fn" : "M_fn") : "U_fn";
+                return kd ? (scalar ? "Sfn" : "Mfn") : "Ufn";
             case INT16 :
-                return kd ? (scalar ? "S_i16" : "M_i16") : "U_i16";
+                return kd ? (scalar ? "Si16" : "Mi16") : "Ui16";
             case INT32 :
-                return kd ? (scalar ? "S_i32" : "M_i32") : "U_i32";
+                return kd ? (scalar ? "Si32" : "Mi32") : "Ui32";
             case INT64 :
-                return kd ? (scalar ? "S_i64" : "M_i64") : "U_i64";
+                return kd ? (scalar ? "Si64" : "Mi64") : "Ui64";
             case INT8 :
-                return kd ? (scalar ? "S_i8" : "M_i8") : "U_i8";
+                return kd ? (scalar ? "Si8" : "Mi8") : "Ui8";
             case LIST :
-                return kd ? (scalar ? "S_l" : "M_l") : "U_l";
+                return kd ? (scalar ? "Sl" : "Ml") : "Ul";
             case LIBRARY :
-                return kd ? (scalar ? "S_lb" : "M_lb") : "U_lb";
+                return kd ? (scalar ? "Slb" : "Mlb") : "Ulb";
             case MACRO :
-                return kd ? (scalar ? "S_m" : "M_m") : "U_m";
+                return kd ? (scalar ? "Sm" : "Mm") : "Um";
             case MACROFILE :
-                return kd ? (scalar ? "S_mf" : "M_mf") : "U_mf";
+                return kd ? (scalar ? "Smf" : "Mmf") : "Umf";
             case MLIST :
-                return kd ? (scalar ? "S_ml" : "M_ml") : "U_ml";
+                return kd ? (scalar ? "Sml" : "Mml") : "Uml";
             case POLYNOMIAL :
-                return kd ? (scalar ? "S_p" : "M_p") : "U_p";
+                return kd ? (scalar ? "Sp" : "Mp") : "Up";
             case STRING :
-                return kd ? (scalar ? "S_s" : "M_s") : "U_s";
+                return kd ? (scalar ? "Ss" : "Ms") : "Us";
             case SPARSE :
-                return kd ? (scalar ? "S_sp" : "M_sp") : "U_sp";
+                return kd ? (scalar ? "Ssp" : "Msp") : "Usp";
             case STRUCT :
-                return kd ? (scalar ? "S_st" : "M_st") : "U_st";
+                return kd ? (scalar ? "Sst" : "Mst") : "Ust";
             case TLIST :
-                return kd ? (scalar ? "S_tl" : "M_tl") : "U_tl";
+                return kd ? (scalar ? "Stl" : "Mtl") : "Utl";
             case UNKNOWN :
-                return kd ? (scalar ? "S_u" : "M_u") : "U_u";
+                return kd ? (scalar ? "Su" : "Mu") : "Uu";
             case UINT16 :
-                return kd ? (scalar ? "S_ui16" : "M_ui16") : "U_ui16";
+                return kd ? (scalar ? "Sui16" : "Mui16") : "Uui16";
             case UINT32 :
-                return kd ? (scalar ? "S_ui32" : "M_ui32") : "U_ui32";
+                return kd ? (scalar ? "Sui32" : "Mui32") : "Uui32";
             case UINT64 :
-                return kd ? (scalar ? "S_ui64" : "M_ui64") : "U_ui64";
+                return kd ? (scalar ? "Sui64" : "Mui64") : "Uui64";
             case UINT8 :
-                return kd ? (scalar ? "S_ui8" : "M_ui8") : "U_ui8";
+                return kd ? (scalar ? "Sui8" : "Mui8") : "Uui8";
             default :
                 return "??";
-            }
         }
+    }
 
-        inline static std::string get_mangling(const TIType::Type ty, const bool scalar)
+    inline static std::string get_mangling(const TIType::Type ty, const bool scalar)
+    {
+        switch (ty)
         {
-            switch (ty)
-            {
             case EMPTY :
                 return "E";
             case BOOLEAN :
-                return scalar ? "S_b" : "M_b";
+                return scalar ? "Sb" : "Mb";
             case COMPLEX :
-                return scalar ? "S_c" : "M_c";
+                return scalar ? "Sc" : "Mc";
             case CELL :
-                return scalar ? "S_ce" : "M_ce";
+                return scalar ? "Sce" : "Mce";
             case DOUBLE :
-                return scalar ? "S_d" : "M_d";
+                return scalar ? "Sd" : "Md";
             case FUNCTION :
-                return scalar ? "S_fn" : "M_fn";
+                return scalar ? "Sfn" : "Mfn";
             case INT16 :
-                return scalar ? "S_i16" : "M_i16";
+                return scalar ? "Si16" : "Mi16";
             case INT32 :
-                return scalar ? "S_i32" : "M_i32";
+                return scalar ? "Si32" : "Mi32";
             case INT64 :
-                return scalar ? "S_i64" : "M_i64";
+                return scalar ? "Si64" : "Mi64";
             case INT8 :
-                return scalar ? "S_i8" : "M_i8";
+                return scalar ? "Si8" : "Mi8";
             case LIST :
-                return scalar ? "S_l" : "M_l";
+                return scalar ? "Sl" : "Ml";
             case LIBRARY :
-                return scalar ? "S_lb" : "M_lb";
+                return scalar ? "Slb" : "Mlb";
             case MACRO :
-                return scalar ? "S_m" : "M_m";
+                return scalar ? "Sm" : "Mm";
             case MACROFILE :
-                return scalar ? "S_mf" : "M_mf";
+                return scalar ? "Smf" : "Mmf";
             case MLIST :
-                return scalar ? "S_ml" : "M_ml";
+                return scalar ? "Sml" : "Mml";
             case POLYNOMIAL :
-                return scalar ? "S_p" : "M_p";
+                return scalar ? "Sp" : "Mp";
             case STRING :
-                return scalar ? "S_s" : "M_s";
+                return scalar ? "Ss" : "Ms";
             case SPARSE :
-                return scalar ? "S_sp" : "M_sp";
+                return scalar ? "Ssp" : "Msp";
             case STRUCT :
-                return scalar ? "S_st" : "M_st";
+                return scalar ? "Sst" : "Mst";
             case TLIST :
-                return scalar ? "S_tl" : "M_tl";
+                return scalar ? "Stl" : "Mtl";
             case UNKNOWN :
-                return scalar ? "S_u" : "M_u";
+                return scalar ? "Su" : "Mu";
             case UINT16 :
-                return scalar ? "S_ui16" : "M_ui16";
+                return scalar ? "Sui16" : "Mui16";
             case UINT32 :
-                return scalar ? "S_ui32" : "M_ui32";
+                return scalar ? "Sui32" : "Mui32";
             case UINT64 :
-                return scalar ? "S_ui64" : "M_ui64";
+                return scalar ? "Sui64" : "Mui64";
             case UINT8 :
-                return scalar ? "S_ui8" : "M_ui8";
+                return scalar ? "Sui8" : "Mui8";
             default :
                 return "??";
-            }
         }
+    }
 
-        inline static std::string get_unary_mangling(const std::string & pre, const TIType & l)
-        {
-            return pre + "_" + l.get_mangling();
-        }
+    inline static std::string get_unary_mangling(const std::string & pre, const TIType & l)
+    {
+        return pre + "_" + l.get_mangling();
+    }
 
-        inline static std::string get_binary_mangling(const std::string & pre, const TIType & l, const TIType & r)
-        {
-            return pre + "_" + l.get_mangling() + "_" + r.get_mangling();
-        }
+    inline static std::string get_binary_mangling(const std::string & pre, const TIType & l, const TIType & r)
+    {
+        return pre + "_" + l.get_mangling() + r.get_mangling();
+    }
 
-        inline static std::string get_mangling(const std::string & pre, const std::vector<TIType> & types)
+    inline static std::string get_mangling(const std::string & pre, const std::vector<TIType> & types)
+    {
+        std::string s(pre);
+        s += "_";
+        for (std::vector<TIType>::const_iterator i = types.begin(), end = types.end(); i != end; ++i)
         {
-           std::string s(pre);
-           for (std::vector<TIType>::const_iterator i = types.begin(), end = types.end(); i != end; ++i)
-           {
-               s += "_" + i->get_mangling();
-           }
-            return s;
+            s += i->get_mangling();
         }
+        return s;
+    }
 
-        inline static unsigned int get_base_size(const Type type)
+    inline static unsigned int get_base_size(const Type type)
+    {
+        switch (type)
         {
-            switch (type)
-            {
             case EMPTY :
                 return sizeof(double);
             case BOOLEAN :
                 return sizeof(int);
             case DOUBLE :
                 return sizeof(double);
-           case INT8 :
-               return sizeof(int8_t);
-           case INT16 :
-               return sizeof(int16_t);
+            case INT8 :
+                return sizeof(int8_t);
+            case INT16 :
+                return sizeof(int16_t);
             case INT32 :
-               return sizeof(int32_t);
+                return sizeof(int32_t);
             case INT64 :
-               return sizeof(int64_t);
-           case UINT8 :
-               return sizeof(uint8_t);
-           case UINT16 :
-               return sizeof(uint16_t);
+                return sizeof(int64_t);
+            case UINT8 :
+                return sizeof(uint8_t);
+            case UINT16 :
+                return sizeof(uint16_t);
             case UINT32 :
-               return sizeof(uint32_t);
+                return sizeof(uint32_t);
             case UINT64 :
-               return sizeof(uint64_t);
+                return sizeof(uint64_t);
             default :
                 return 0;
-            }
         }
+    }
 
-        inline static std::wstring toString(Type t)
+    inline static std::wstring toString(Type t)
+    {
+        switch (t)
         {
-            switch (t)
-            {
             case EMPTY :
                 return L"[]";
             case BOOLEAN :
@@ -404,18 +405,18 @@ namespace analysis
                 return L"uint8";
             default :
                 return L"unknown";
-            }
         }
+    }
 
-        inline const std::wstring & getScilabString() const
-        {
-            return getScilabString(type);
-        }
+    inline const std::wstring & getScilabString() const
+    {
+        return getScilabString(type);
+    }
 
-        inline static const std::wstring & getScilabString(Type t)
+    inline static const std::wstring & getScilabString(Type t)
+    {
+        switch (t)
         {
-            switch (t)
-            {
             case EMPTY :
                 return _constant_;
             case BOOLEAN :
@@ -468,18 +469,18 @@ namespace analysis
                 return _uint8_;
             default :
                 return _unknown_;
-            }
         }
+    }
 
-        inline int getScilabCode() const
-        {
-            return getScilabCode(type);
-        }
+    inline int getScilabCode() const
+    {
+        return getScilabCode(type);
+    }
 
-        inline static int getScilabCode(Type t)
+    inline static int getScilabCode(Type t)
+    {
+        switch (t)
         {
-            switch (t)
-            {
             case EMPTY :
                 return 1;
             case BOOLEAN :
@@ -532,13 +533,13 @@ namespace analysis
                 return 8;
             default :
                 return -1;
-            }
         }
+    }
 
-       friend std::wostream & operator<<(std::wostream & out, const TIType & type)
+    friend std::wostream & operator<<(std::wostream & out, const TIType & type)
+    {
+        switch (type.type)
         {
-            switch (type.type)
-            {
             case EMPTY :
                 out << L"[]";
                 break;
@@ -616,48 +617,78 @@ namespace analysis
                 break;
             default :
                 break;
-            }
+        }
 
-            if (type.type != EMPTY && type.type != UNKNOWN)
+        if (type.type != EMPTY && type.type != UNKNOWN)
+        {
+            if (type.isUnknownDims())
             {
-                if (type.isUnknownDims())
-                {
-                    out << L"[?, ?]";
-                }
-                else
-                {
-                    out << L"[" << type.rows << L", " << type.cols << L"]";
-                }
-           }
-
-            return out;
+                out << L"[?, ?]";
+            }
+            else
+            {
+                out << L"[" << type.rows << L", " << type.cols << L"]";
+            }
         }
-    };
-
-    template<> inline TIType::Type TIType::getTI<bool>() { return TIType::BOOLEAN; }
-    template<> inline TIType::Type TIType::getTI<double>() { return TIType::DOUBLE; }
-    template<> inline TIType::Type TIType::getTI<int16_t>() { return TIType::INT16; }
-    template<> inline TIType::Type TIType::getTI<int32_t>() { return TIType::INT32; }
-    template<> inline TIType::Type TIType::getTI<int64_t>() { return TIType::INT64; }
-    template<> inline TIType::Type TIType::getTI<int8_t>() { return TIType::INT8; }
-    template<> inline TIType::Type TIType::getTI<uint16_t>() { return TIType::UINT16; }
-    template<> inline TIType::Type TIType::getTI<uint32_t>() { return TIType::UINT32; }
-    template<> inline TIType::Type TIType::getTI<uint64_t>() { return TIType::UINT64; }
-    template<> inline TIType::Type TIType::getTI<uint8_t>() { return TIType::UINT8; }
+
+        return out;
+    }
+};
+
+template<> inline TIType::Type TIType::getTI<bool>()
+{
+    return TIType::BOOLEAN;
+}
+template<> inline TIType::Type TIType::getTI<double>()
+{
+    return TIType::DOUBLE;
+}
+template<> inline TIType::Type TIType::getTI<int16_t>()
+{
+    return TIType::INT16;
+}
+template<> inline TIType::Type TIType::getTI<int32_t>()
+{
+    return TIType::INT32;
+}
+template<> inline TIType::Type TIType::getTI<int64_t>()
+{
+    return TIType::INT64;
+}
+template<> inline TIType::Type TIType::getTI<int8_t>()
+{
+    return TIType::INT8;
+}
+template<> inline TIType::Type TIType::getTI<uint16_t>()
+{
+    return TIType::UINT16;
+}
+template<> inline TIType::Type TIType::getTI<uint32_t>()
+{
+    return TIType::UINT32;
+}
+template<> inline TIType::Type TIType::getTI<uint64_t>()
+{
+    return TIType::UINT64;
+}
+template<> inline TIType::Type TIType::getTI<uint8_t>()
+{
+    return TIType::UINT8;
+}
 
 } // namespace analysis
 
 namespace std
 {
-    // useful to be able to put TIType in unorderd_set for example.
-    template<>
-    struct hash<analysis::TIType>
-    {
-       inline size_t operator()(const analysis::TIType & t) const
-           {
-               return 0;//tools::hash_combine(t.type, t.rows, t.cols);
-           }
-    };
+// useful to be able to put TIType in unorderd_set for example.
+template<>
+struct hash<analysis::TIType>
+{
+    inline size_t operator()(const analysis::TIType & t) const
+    {
+        return 0;//tools::hash_combine(t.type, t.rows, t.cols);
+    }
+};
 } // namespace std
 
 #endif // __TITYPE_HXX__
\ No newline at end of file
index df3247b..c592462 100644 (file)
 
 namespace analysis
 {
-    class Checkers
+class Checkers
+{
+    struct __NName
     {
-        struct __NName
-        {
-            const unsigned short nargs;
-            const std::wstring name;
+        const unsigned short nargs;
+        const std::wstring name;
 
-            //__NName(unsigned short n, const char * _name) : nargs(n), name(_name) { }
-            __NName(unsigned short n, const std::wstring & _name) : nargs(n), name(_name) { }
-            inline bool operator==(const __NName & R) const { return nargs == R.nargs && name == R.name; }
-        };
+        //__NName(unsigned short n, const char * _name) : nargs(n), name(_name) { }
+        __NName(unsigned short n, const std::wstring & _name) : nargs(n), name(_name) { }
+        inline bool operator==(const __NName & R) const
+        {
+            return nargs == R.nargs && name == R.name;
+        }
+    };
 
-       struct __Infos
-       {
-           const unsigned short pos;
-           const bool elementwise;
-           const bool notconst;
-           const bool jitted;
+    struct __Infos
+    {
+        const unsigned short pos;
+        const bool elementwise;
+        const bool notconst;
+        const bool jitted;
 
-           __Infos(const unsigned short _pos, const bool _ew, const bool _nc, const bool _j) : pos(_pos), elementwise(_ew), notconst(_nc), jitted(_j) { }
-       };
+        __Infos(const unsigned short _pos, const bool _ew, const bool _nc, const bool _j) : pos(_pos), elementwise(_ew), notconst(_nc), jitted(_j) { }
+    };
 
-        struct __Hasher
+    struct __Hasher
+    {
+        inline std::size_t operator()(const __NName & nn) const
         {
-            inline std::size_t operator()(const __NName & nn) const { return tools::hash_combine(std::hash<std::wstring>()(nn.name), nn.nargs); }
-        };
-
-        typedef std::unordered_map<__NName, __Infos, __Hasher> CheckersMap;
-        static CheckersMap map;
-        static TIType (*ARGS0[6])(GVN &);
-        static TIType (*ARGS1[53])(GVN &, const TIType &);
-        static TIType (*ARGS2[10])(GVN &, const TIType &, const TIType &);
-        static TIType (*ARGS3[1])(GVN &, const TIType &, const TIType &, const TIType &);
-
-    public:
-        
-        static TIType check(GVN & gvn, const std::wstring & name, const std::vector<TIType> & args);
-        static bool isElementWise(const std::wstring & name, unsigned short nargs = 1);
-        static bool isJitted(const std::wstring & name, unsigned short nargs = 1);
-        static bool isConst(const std::wstring & name, unsigned short nargs = 1);
-
-    private:
-
-        static CheckersMap initMap();
-
-    public:
-        
-        static TIType check_____dotpower____(GVN & gvn, const TIType & in0, const TIType & in1);
-        static TIType check_rand(GVN & gvn);
-        static TIType check_rand(GVN & gvn, const TIType & in0);
-        static TIType check_rand(GVN & gvn, const TIType & in0, const TIType & in1);
-        static TIType check_____ge____(GVN & gvn, const TIType & in0, const TIType & in1);
-        static TIType check_____or____(GVN & gvn, const TIType & in0, const TIType & in1);
-        static TIType check_____power____(GVN & gvn, const TIType & in0, const TIType & in1);
-        static TIType check_____not____(GVN & gvn, const TIType & in0);
-        static TIType check_isreal(GVN & gvn, const TIType & in0);
-        static TIType check_isreal(GVN & gvn, const TIType & in0, const TIType & in1);
-        static TIType check_____transp____(GVN & gvn, const TIType & in0);
-        static TIType check_abs(GVN & gvn, const TIType & in0);
-        static TIType check_cosh(GVN & gvn, const TIType & in0);
-        static TIType check_typeof(GVN & gvn, const TIType & in0);
-        static TIType check_int16(GVN & gvn, const TIType & in0);
-        static TIType check_iconvert(GVN & gvn, const TIType & in0, const TIType & in1);
-        static TIType check_gettext(GVN & gvn, const TIType & in0);
-        static TIType check_gettext(GVN & gvn, const TIType & in0, const TIType & in1);
-        static TIType check_____neq____(GVN & gvn, const TIType & in0, const TIType & in1);
-        static TIType check_____and____(GVN & gvn, const TIType & in0, const TIType & in1);
-        static TIType check_tan(GVN & gvn, const TIType & in0);
-        static TIType check_cumsum(GVN & gvn, const TIType & in0);
-        static TIType check_size(GVN & gvn, const TIType & in0);
-        static TIType check_size(GVN & gvn, const TIType & in0, const TIType & in1);
-        static TIType check_____andand____(GVN & gvn, const TIType & in0, const TIType & in1);
-        static TIType check_asin(GVN & gvn, const TIType & in0);
-        static TIType check_____dottransp____(GVN & gvn, const TIType & in0);
-        static TIType check_or(GVN & gvn, const TIType & in0);
-        static TIType check_or(GVN & gvn, const TIType & in0, const TIType & in1);
-        static TIType check_____eq____(GVN & gvn, const TIType & in0, const TIType & in1);
-        static TIType check_log(GVN & gvn, const TIType & in0);
-        static TIType check_floor(GVN & gvn, const TIType & in0);
-        static TIType check_int(GVN & gvn, const TIType & in0);
-        static TIType check_fix(GVN & gvn, const TIType & in0);
-        static TIType check_sqrt(GVN & gvn, const TIType & in0);
-        static TIType check_uint16(GVN & gvn, const TIType & in0);
-        static TIType check_____le____(GVN & gvn, const TIType & in0, const TIType & in1);
-        static TIType check_zeros(GVN & gvn);
-        static TIType check_zeros(GVN & gvn, const TIType & in0);
-        static TIType check_zeros(GVN & gvn, const TIType & in0, const TIType & in1);
-        static TIType check_ls(GVN & gvn);
-        static TIType check_ls(GVN & gvn, const TIType & in0);
-        static TIType check_max(GVN & gvn, const TIType & in0);
-        static TIType check_uint32(GVN & gvn, const TIType & in0);
-        static TIType check_int64(GVN & gvn, const TIType & in0);
-        static TIType check_prod(GVN & gvn, const TIType & in0);
-        static TIType check_type(GVN & gvn, const TIType & in0);
-        static TIType check_sin(GVN & gvn, const TIType & in0);
-        static TIType check_round(GVN & gvn, const TIType & in0);
-        static TIType check_____krontimes____(GVN & gvn, const TIType & in0, const TIType & in1);
-        static TIType check_int32(GVN & gvn, const TIType & in0);
-        static TIType check_____gt____(GVN & gvn, const TIType & in0, const TIType & in1);
-        static TIType check_inttype(GVN & gvn, const TIType & in0);
-        static TIType check_exp(GVN & gvn, const TIType & in0);
-        static TIType check_atan(GVN & gvn, const TIType & in0);
-        static TIType check_____dotrdiv____(GVN & gvn, const TIType & in0, const TIType & in1);
-        static TIType check_imag(GVN & gvn, const TIType & in0);
-        static TIType check_uint8(GVN & gvn, const TIType & in0);
-        static TIType check_ceil(GVN & gvn, const TIType & in0);
-        static TIType check_uint64(GVN & gvn, const TIType & in0);
-        static TIType check_____lt____(GVN & gvn, const TIType & in0, const TIType & in1);
-        static TIType check_sinm(GVN & gvn, const TIType & in0);
-        static TIType check_isinf(GVN & gvn, const TIType & in0);
-        static TIType check_____sub____(GVN & gvn, const TIType & in0, const TIType & in1);
-        static TIType check_sinh(GVN & gvn, const TIType & in0);
-        static TIType check_toc(GVN & gvn);
-        static TIType check_isscalar(GVN & gvn, const TIType & in0);
-        static TIType check_int8(GVN & gvn, const TIType & in0);
-        static TIType check_____rdivide____(GVN & gvn, const TIType & in0, const TIType & in1);
-        static TIType check_matrix(GVN & gvn, const TIType & in0, const TIType & in1);
-        static TIType check_matrix(GVN & gvn, const TIType & in0, const TIType & in1, const TIType & in2);
-        static TIType check_____oror____(GVN & gvn, const TIType & in0, const TIType & in1);
-        static TIType check_cos(GVN & gvn, const TIType & in0);
-        static TIType check_and(GVN & gvn, const TIType & in0);
-        static TIType check_and(GVN & gvn, const TIType & in0, const TIType & in1);
-        static TIType check_____unaryminus____(GVN & gvn, const TIType & in0);
-        static TIType check_tanh(GVN & gvn, const TIType & in0);
-        static TIType check_____add____(GVN & gvn, const TIType & in0, const TIType & in1);
-        static TIType check_isnan(GVN & gvn, const TIType & in0);
-        static TIType check_imult(GVN & gvn, const TIType & in0);
-        static TIType check_____times____(GVN & gvn, const TIType & in0, const TIType & in1);
-        static TIType check_argn(GVN & gvn);
-        static TIType check_argn(GVN & gvn, const TIType & in0);
-        static TIType check_cumprod(GVN & gvn, const TIType & in0);
-        static TIType check_erf(GVN & gvn, const TIType & in0);
-        static TIType check_ones(GVN & gvn);
-        static TIType check_ones(GVN & gvn, const TIType & in0);
-        static TIType check_ones(GVN & gvn, const TIType & in0, const TIType & in1);
-        static TIType check_erfc(GVN & gvn, const TIType & in0);
-        static TIType check_min(GVN & gvn, const TIType & in0);
-        static TIType check_sum(GVN & gvn, const TIType & in0);
-        static TIType check_____ldivide____(GVN & gvn, const TIType & in0, const TIType & in1);
-        static TIType check_acos(GVN & gvn, const TIType & in0);
-        static TIType check_____dottimes____(GVN & gvn, const TIType & in0, const TIType & in1);
+            return tools::hash_combine(std::hash<std::wstring>()(nn.name), nn.nargs);
+        }
     };
 
+    typedef std::unordered_map<__NName, __Infos, __Hasher> CheckersMap;
+    static CheckersMap map;
+    static TIType (*ARGS0[6])(GVN &);
+    static TIType (*ARGS1[54])(GVN &, const TIType &);
+    static TIType (*ARGS2[10])(GVN &, const TIType &, const TIType &);
+    static TIType (*ARGS3[1])(GVN &, const TIType &, const TIType &, const TIType &);
+
+public:
+
+    static TIType check(GVN & gvn, const std::wstring & name, const std::vector<TIType> & args);
+    static bool isElementWise(const std::wstring & name, unsigned short nargs = 1);
+    static bool isJitted(const std::wstring & name, unsigned short nargs = 1);
+    static bool isConst(const std::wstring & name, unsigned short nargs = 1);
+
+private:
+
+    static CheckersMap initMap();
+
+public:
+
+    static TIType check_____dotpower____(GVN & gvn, const TIType & in0, const TIType & in1);
+    static TIType check_rand(GVN & gvn);
+    static TIType check_rand(GVN & gvn, const TIType & in0);
+    static TIType check_rand(GVN & gvn, const TIType & in0, const TIType & in1);
+    static TIType check_____ge____(GVN & gvn, const TIType & in0, const TIType & in1);
+    static TIType check_____or____(GVN & gvn, const TIType & in0, const TIType & in1);
+    static TIType check_____power____(GVN & gvn, const TIType & in0, const TIType & in1);
+    static TIType check_____not____(GVN & gvn, const TIType & in0);
+    static TIType check_isreal(GVN & gvn, const TIType & in0);
+    static TIType check_isreal(GVN & gvn, const TIType & in0, const TIType & in1);
+    static TIType check_____transp____(GVN & gvn, const TIType & in0);
+    static TIType check_abs(GVN & gvn, const TIType & in0);
+    static TIType check_cosh(GVN & gvn, const TIType & in0);
+    static TIType check_typeof(GVN & gvn, const TIType & in0);
+    static TIType check_int16(GVN & gvn, const TIType & in0);
+    static TIType check_iconvert(GVN & gvn, const TIType & in0, const TIType & in1);
+    static TIType check_gettext(GVN & gvn, const TIType & in0);
+    static TIType check_gettext(GVN & gvn, const TIType & in0, const TIType & in1);
+    static TIType check_____neq____(GVN & gvn, const TIType & in0, const TIType & in1);
+    static TIType check_____and____(GVN & gvn, const TIType & in0, const TIType & in1);
+    static TIType check_tan(GVN & gvn, const TIType & in0);
+    static TIType check_cumsum(GVN & gvn, const TIType & in0);
+    static TIType check_size(GVN & gvn, const TIType & in0);
+    static TIType check_size(GVN & gvn, const TIType & in0, const TIType & in1);
+    static TIType check_____andand____(GVN & gvn, const TIType & in0, const TIType & in1);
+    static TIType check_asin(GVN & gvn, const TIType & in0);
+    static TIType check_____dottransp____(GVN & gvn, const TIType & in0);
+    static TIType check_or(GVN & gvn, const TIType & in0);
+    static TIType check_or(GVN & gvn, const TIType & in0, const TIType & in1);
+    static TIType check_____eq____(GVN & gvn, const TIType & in0, const TIType & in1);
+    static TIType check_log(GVN & gvn, const TIType & in0);
+    static TIType check_floor(GVN & gvn, const TIType & in0);
+    static TIType check_int(GVN & gvn, const TIType & in0);
+    static TIType check_fix(GVN & gvn, const TIType & in0);
+    static TIType check_sqrt(GVN & gvn, const TIType & in0);
+    static TIType check_uint16(GVN & gvn, const TIType & in0);
+    static TIType check_____le____(GVN & gvn, const TIType & in0, const TIType & in1);
+    static TIType check_zeros(GVN & gvn);
+    static TIType check_zeros(GVN & gvn, const TIType & in0);
+    static TIType check_zeros(GVN & gvn, const TIType & in0, const TIType & in1);
+    static TIType check_ls(GVN & gvn);
+    static TIType check_ls(GVN & gvn, const TIType & in0);
+    static TIType check_max(GVN & gvn, const TIType & in0);
+    static TIType check_uint32(GVN & gvn, const TIType & in0);
+    static TIType check_int64(GVN & gvn, const TIType & in0);
+    static TIType check_prod(GVN & gvn, const TIType & in0);
+    static TIType check_type(GVN & gvn, const TIType & in0);
+    static TIType check_sin(GVN & gvn, const TIType & in0);
+    static TIType check_round(GVN & gvn, const TIType & in0);
+    static TIType check_____krontimes____(GVN & gvn, const TIType & in0, const TIType & in1);
+    static TIType check_int32(GVN & gvn, const TIType & in0);
+    static TIType check_____gt____(GVN & gvn, const TIType & in0, const TIType & in1);
+    static TIType check_inttype(GVN & gvn, const TIType & in0);
+    static TIType check_exp(GVN & gvn, const TIType & in0);
+    static TIType check_atan(GVN & gvn, const TIType & in0);
+    static TIType check_____dotrdiv____(GVN & gvn, const TIType & in0, const TIType & in1);
+    static TIType check_imag(GVN & gvn, const TIType & in0);
+    static TIType check_uint8(GVN & gvn, const TIType & in0);
+    static TIType check_ceil(GVN & gvn, const TIType & in0);
+    static TIType check_uint64(GVN & gvn, const TIType & in0);
+    static TIType check_____lt____(GVN & gvn, const TIType & in0, const TIType & in1);
+    static TIType check_sinm(GVN & gvn, const TIType & in0);
+    static TIType check_isinf(GVN & gvn, const TIType & in0);
+    static TIType check_____sub____(GVN & gvn, const TIType & in0, const TIType & in1);
+    static TIType check_sinh(GVN & gvn, const TIType & in0);
+    static TIType check_toc(GVN & gvn);
+    static TIType check_isscalar(GVN & gvn, const TIType & in0);
+    static TIType check_sign(GVN & gvn, const TIType & in0);
+    static TIType check_int8(GVN & gvn, const TIType & in0);
+    static TIType check_____rdivide____(GVN & gvn, const TIType & in0, const TIType & in1);
+    static TIType check_matrix(GVN & gvn, const TIType & in0, const TIType & in1);
+    static TIType check_matrix(GVN & gvn, const TIType & in0, const TIType & in1, const TIType & in2);
+    static TIType check_____oror____(GVN & gvn, const TIType & in0, const TIType & in1);
+    static TIType check_cos(GVN & gvn, const TIType & in0);
+    static TIType check_and(GVN & gvn, const TIType & in0);
+    static TIType check_and(GVN & gvn, const TIType & in0, const TIType & in1);
+    static TIType check_____unaryminus____(GVN & gvn, const TIType & in0);
+    static TIType check_tanh(GVN & gvn, const TIType & in0);
+    static TIType check_____add____(GVN & gvn, const TIType & in0, const TIType & in1);
+    static TIType check_isnan(GVN & gvn, const TIType & in0);
+    static TIType check_imult(GVN & gvn, const TIType & in0);
+    static TIType check_____times____(GVN & gvn, const TIType & in0, const TIType & in1);
+    static TIType check_argn(GVN & gvn);
+    static TIType check_argn(GVN & gvn, const TIType & in0);
+    static TIType check_cumprod(GVN & gvn, const TIType & in0);
+    static TIType check_erf(GVN & gvn, const TIType & in0);
+    static TIType check_ones(GVN & gvn);
+    static TIType check_ones(GVN & gvn, const TIType & in0);
+    static TIType check_ones(GVN & gvn, const TIType & in0, const TIType & in1);
+    static TIType check_erfc(GVN & gvn, const TIType & in0);
+    static TIType check_min(GVN & gvn, const TIType & in0);
+    static TIType check_sum(GVN & gvn, const TIType & in0);
+    static TIType check_____ldivide____(GVN & gvn, const TIType & in0, const TIType & in1);
+    static TIType check_acos(GVN & gvn, const TIType & in0);
+    static TIType check_____dottimes____(GVN & gvn, const TIType & in0, const TIType & in1);
+};
+
 } // namespace analysis
 
 #endif // __CHECKERS_HXX__
\ No newline at end of file
index 5862b25..a553b97 100644 (file)
 #include "symbol.hxx"
 #include "TIType.hxx"
 #include "gvn/GVN.hxx"
+#include "tools.hxx"
 #include "dynlib_ast.h"
 
 namespace analysis
 {
-    class AnalysisVisitor;
-    class DataManager;
+class AnalysisVisitor;
+class DataManager;
 
-    class EXTERN_AST Block
-    {
+class EXTERN_AST Block
+{
 
-        friend class DataManager;
+    friend class DataManager;
 
-    protected:
+protected:
 
-        DataManager * dm;
-        ast::Exp * exp;
-        Block * parent;
-        std::map<symbol::Symbol, Info> symMap;
-        std::vector<Block *> blocks;
-        GVN * gvn;
-        bool isReturn;
-        const unsigned int id;
+    DataManager * dm;
+    ast::Exp * exp;
+    Block * parent;
+    tools::SymbolMap<Info> symMap;
+    std::vector<Block *> blocks;
+    GVN * gvn;
+    bool isReturn;
+    const unsigned int id;
 
-    public:
+public:
 
-        enum BlockKind
-        {
-            NORMAL, LOOP, EXCLUSIVE, MACRO
-        };
+    enum BlockKind
+    {
+        NORMAL, LOOP, EXCLUSIVE, MACRO
+    };
 
-        Block(DataManager * _dm);
-        Block(const unsigned int _id, Block * _parent, ast::Exp * _exp) : dm(_parent->dm), parent(_parent), exp(_exp), gvn(&_parent->getGVN()), isReturn(false), id(_id) { }
+    Block(DataManager * _dm);
+    Block(const unsigned int _id, Block * _parent, ast::Exp * _exp) : dm(_parent->dm), parent(_parent), exp(_exp), gvn(&_parent->getGVN()), isReturn(false), id(_id) { }
 
-        virtual ~Block();
+    virtual ~Block();
 
-        inline std::map<symbol::Symbol, Info> & getMap()
-        {
-            return symMap;
-        }
+    inline tools::SymbolMap<Info> & getMap()
+    {
+        return symMap;
+    }
 
-        inline Info & addSym(const symbol::Symbol & sym, Data * data)
-        {
+    inline Info & addSym(const symbol::Symbol & sym, Data * data)
+    {
 #ifdef DEBUG_DATAMANAGER
-            if (symMap.find(sym) != symMap.end())
-            {
-                std::wcerr << L"Table " << id << L" already contains " << sym << std::endl;
-            }
-#endif
-            return symMap.emplace(sym, data).first->second;
-        }
-
-        inline Info & addSym(const symbol::Symbol & sym, const Info & info)
+        if (symMap.find(sym) != symMap.end())
         {
-#ifdef DEBUG_DATAMANAGER
-            if (symMap.find(sym) != symMap.end())
-            {
-                std::wcerr << L"Table " << id << L" already contains " << sym << std::endl;
-            }
-#endif
-            return symMap.emplace(sym, info).first->second;
+            std::wcerr << L"Table " << id << L" already contains " << sym << std::endl;
         }
+#endif
+        return symMap.emplace(sym, data).first->second;
+    }
 
-        inline ast::Exp * getExp()
+    inline Info & addSym(const symbol::Symbol & sym, const Info & info)
+    {
+#ifdef DEBUG_DATAMANAGER
+        if (symMap.find(sym) != symMap.end())
         {
-            return exp;
+            std::wcerr << L"Table " << id << L" already contains " << sym << std::endl;
         }
+#endif
+        return symMap.emplace(sym, info).first->second;
+    }
 
-        inline void setReturn(const bool _isReturn)
-        {
-            isReturn = _isReturn;
-        }
+    inline ast::Exp * getExp()
+    {
+        return exp;
+    }
 
-        inline bool getReturn() const
-        {
-            return isReturn;
-       }
-
-       static Info & addSym(std::map<symbol::Symbol, Info> & M, const symbol::Symbol & sym, Info & info);
-
-        Info & setDefaultData(const symbol::Symbol & sym);
-        void merge(std::map<symbol::Symbol, Info> & M, std::map<symbol::Symbol, Info> & N);
-        void pullup(std::map<symbol::Symbol, Info> & M);
-        Info & putSymsInScope(const symbol::Symbol & sym, Block * block, Info & info);
-        Info & putSymsInScope(const symbol::Symbol & sym);
-        Info & putAndClear(const symbol::Symbol & sym, ast::Exp * exp);
-
-       virtual void addLocal(const symbol::Symbol & sym, const TIType & type, const bool isIntIterator);
-       virtual int getTmpId(const TIType & type, const bool isIntIterator);
-       virtual void releaseTmp(const int id);
-        virtual Info & addRead(const symbol::Symbol & sym, ast::Exp * exp);
-        virtual Info & addWrite(const symbol::Symbol & sym, const TIType & Rtype, ast::Exp * exp);
-        virtual Info & addDefine(const symbol::Symbol & sym, const TIType & Rtype, const bool isAnInt, ast::Exp * exp);
-        virtual Info & addShare(const symbol::Symbol & Lsym, const symbol::Symbol & Rsym, const TIType & Rtype, ast::Exp * exp);
-        virtual Info & addMacroDef(ast::FunctionDec * dec);
-        virtual std::vector<TIType> addCall(AnalysisVisitor & visitor, const unsigned int lhs, const symbol::Symbol & sym, std::vector<TIType> & in, ast::CallExp * callexp);
-        virtual Info & addClear(const symbol::Symbol & sym, ast::Exp * exp);
-
-        virtual Block * getDefBlock(const symbol::Symbol & sym, std::map<symbol::Symbol, Info>::iterator & it, const bool global);
-        virtual Info & getInfo(const symbol::Symbol & sym);
-        virtual Block * addBlock(const unsigned int id, BlockKind kind, ast::Exp * exp);
-        virtual void finalize();
-        virtual bool requiresAnotherTrip();
-        virtual void addGlobal(const symbol::Symbol & sym);
-        virtual GVN & getGVN();
-
-        friend std::wostream & operator<<(std::wostream & out, const Block & block);
-    };
+    inline void setReturn(const bool _isReturn)
+    {
+        isReturn = _isReturn;
+    }
+
+    inline bool getReturn() const
+    {
+        return isReturn;
+    }
+
+    static Info & addSym(tools::SymbolMap<Info> & M, const symbol::Symbol & sym, Info & info);
+
+    Info & setDefaultData(const symbol::Symbol & sym);
+    void merge(tools::SymbolMap<Info> & M, tools::SymbolMap<Info> & N);
+    void pullup(tools::SymbolMap<Info> & M);
+    Info & putSymsInScope(const symbol::Symbol & sym, Block * block, Info & info);
+    Info & putSymsInScope(const symbol::Symbol & sym);
+    Info & putAndClear(const symbol::Symbol & sym, ast::Exp * exp);
+    void clone(Info & info, const symbol::Symbol & sym, ast::Exp * exp);
+
+    virtual void addLocal(const symbol::Symbol & sym, const TIType & type, const bool isIntIterator);
+    virtual int getTmpId(const TIType & type, const bool isIntIterator);
+    virtual void releaseTmp(const int id);
+    virtual Info & addRead(const symbol::Symbol & sym, ast::Exp * exp);
+    virtual Info & addWrite(const symbol::Symbol & sym, const TIType & Rtype, ast::Exp * exp);
+    virtual Info & addDefine(const symbol::Symbol & sym, const TIType & Rtype, const bool isAnInt, ast::Exp * exp);
+    virtual Info & addShare(const symbol::Symbol & Lsym, const symbol::Symbol & Rsym, const TIType & Rtype, ast::Exp * exp);
+    virtual Info & addMacroDef(ast::FunctionDec * dec);
+    virtual std::vector<TIType> addCall(AnalysisVisitor & visitor, const unsigned int lhs, const symbol::Symbol & sym, std::vector<TIType> & in, ast::CallExp * callexp);
+    virtual Info & addClear(const symbol::Symbol & sym, ast::Exp * exp);
+
+    virtual Block * getDefBlock(const symbol::Symbol & sym, tools::SymbolMap<Info>::iterator & it, const bool global);
+    virtual Info & getInfo(const symbol::Symbol & sym);
+    virtual Block * addBlock(const unsigned int id, BlockKind kind, ast::Exp * exp);
+    virtual void finalize();
+    virtual bool requiresAnotherTrip();
+    virtual void addGlobal(const symbol::Symbol & sym);
+    virtual GVN & getGVN();
+    virtual void clone(const symbol::Symbol & sym, ast::Exp * exp);
+
+    friend std::wostream & operator<<(std::wostream & out, const Block & block);
+};
 
 } // namespace analysis
 
diff --git a/scilab/modules/ast/includes/analysis/data/Clone.hxx b/scilab/modules/ast/includes/analysis/data/Clone.hxx
new file mode 100644 (file)
index 0000000..d550fda
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+ *  Copyright (C) 2015 - Scilab Enterprises - Calixte DENIZET
+ *
+ *  This file must be used under the terms of the CeCILL.
+ *  This source file is licensed as described in the file COPYING, which
+ *  you should have received as part of this distribution.  The terms
+ *  are also available at
+ *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
+ *
+ */
+
+#ifndef __CLONE_HXX__
+#define __CLONE_HXX__
+
+#include <iostream>
+
+#include "tools.hxx"
+
+namespace analysis
+{
+
+class Clone
+{
+
+    tools::SymbolSet set;
+
+public:
+
+    Clone() { }
+    Clone(const symbol::Symbol & sym)
+    {
+        add(sym);
+    }
+
+    inline void add(const symbol::Symbol & sym)
+    {
+        set.emplace(sym);
+    }
+
+    inline const tools::SymbolSet & get() const
+    {
+        return set;
+    }
+
+    inline void clear()
+    {
+        set.clear();
+    }
+
+    friend std::wostream & operator<<(std::wostream & out, const Clone & c)
+    {
+        out << L"Clone";
+        tools::printSet(c.set, out);
+
+        return out;
+    }
+};
+
+} // namespace analysis
+
+
+#endif // __CLONE_HXX__
index d45ef65..1951b66 100644 (file)
@@ -16,6 +16,7 @@
 #include <iostream>
 #include <set>
 
+#include "tools.hxx"
 #include "symbol.hxx"
 
 namespace analysis
@@ -25,7 +26,7 @@ struct Data
 {
     bool known;
     bool valid;
-    std::set<symbol::Symbol> sharedSyms;
+    tools::SymbolSet sharedSyms;
 
     Data(const bool _known, const symbol::Symbol & sym);
     Data(const Data & d) : known(d.known), valid(true), sharedSyms(d.sharedSyms) {  }
index ac45cb8..a712384 100644 (file)
 namespace analysis
 {
 
-    class AnalysisVisitor;
-    class FunctionBlock;
-    class MacroDef;
-    class Data;
-    class Info;
+class AnalysisVisitor;
+class FunctionBlock;
+class MacroDef;
+class Data;
+class Info;
 
-    class DataManager
+class DataManager
+{
+    friend class Block;
+
+    Block * root;
+    Block * current;
+    std::vector<Data *> data;
+    unsigned int id;
+    tools::SymbolSet globals;
+    std::stack<FunctionBlock *> callStack;
+    std::unordered_map<types::Macro *, MacroDef *> macroDefCache;
+    GVN gvn;
+
+public:
+
+    DataManager();
+
+    ~DataManager();
+
+    GVN & getGVN();
+    GVN & getDefaultGVN();
+    MacroDef * getMacroDef(types::Macro * macro);
+    void addGlobal(const symbol::Symbol & sym);
+    void registerData(Data * _data, int line = 0, char * file = nullptr);
+    int getTmpId(const TIType & type, const bool isAnInt);
+    void releaseTmp(const int id);
+    Info & read(const symbol::Symbol & sym, ast::Exp * exp);
+    Info & write(const symbol::Symbol & sym, const TIType & Rtype, ast::Exp * exp);
+    Info & define(const symbol::Symbol & sym, const TIType & Rtype, const bool isAnInt, ast::Exp * exp);
+    Info & share(const symbol::Symbol & Lsym, const symbol::Symbol & Rsym, const TIType & Rtype, ast::Exp * exp);
+    Info & clear(const symbol::Symbol & sym, ast::Exp * exp);
+    Info & macrodef(ast::Exp * exp);
+    std::vector<TIType> call(AnalysisVisitor & visitor, const unsigned int lhs, const symbol::Symbol & sym, std::vector<TIType> & in, ast::CallExp * callexp);
+    void addBlock(Block::BlockKind kind, ast::Exp * exp);
+    Block * getCurrent();
+    void finalizeBlock();
+    bool requiresAnotherTrip();
+    void pushFunction(FunctionBlock * fblock);
+    FunctionBlock * poptopFunction();
+    FunctionBlock * topFunction();
+    void popFunction();
+    TIType getType(const symbol::Symbol & sym, const bool global = false);
+    Info & getInfo(const symbol::Symbol & sym);
+    friend std::wostream & operator<<(std::wostream & out, const DataManager & dm);
+
+    template<typename T>
+    bool getTypes(std::vector<TIType> & out, const T & syms)
     {
-        friend class Block;
-
-       Block * root;
-        Block * current;
-        std::vector<Data *> data;
-        unsigned int id;
-        std::set<symbol::Symbol> globals;
-        std::stack<FunctionBlock *> callStack;
-       std::unordered_map<types::Macro *, MacroDef *> macroDefCache;
-        GVN gvn;
-
-    public:
-
-        DataManager();
-       
-        ~DataManager();
-
-        GVN & getGVN();
-        GVN & getDefaultGVN();
-       MacroDef * getMacroDef(types::Macro * macro);
-        void addGlobal(const symbol::Symbol & sym);
-        void registerData(Data * _data, int line = 0, char * file = nullptr);
-       int getTmpId(const TIType & type, const bool isAnInt);
-       void releaseTmp(const int id);
-        Info & read(const symbol::Symbol & sym, ast::Exp * exp);
-        Info & write(const symbol::Symbol & sym, const TIType & Rtype, ast::Exp * exp);
-        Info & define(const symbol::Symbol & sym, const TIType & Rtype, const bool isAnInt, ast::Exp * exp);
-        Info & share(const symbol::Symbol & Lsym, const symbol::Symbol & Rsym, const TIType & Rtype, ast::Exp * exp);
-        Info & clear(const symbol::Symbol & sym, ast::Exp * exp);
-        Info & macrodef(ast::Exp * exp);
-        std::vector<TIType> call(AnalysisVisitor & visitor, const unsigned int lhs, const symbol::Symbol & sym, std::vector<TIType> & in, ast::CallExp * callexp);
-        void addBlock(Block::BlockKind kind, ast::Exp * exp);
-        Block * getCurrent();
-        void finalizeBlock();
-        bool requiresAnotherTrip();
-        void pushFunction(FunctionBlock * fblock);
-        FunctionBlock * poptopFunction();
-        FunctionBlock * topFunction();
-        void popFunction();
-       TIType getType(const symbol::Symbol & sym, const bool global = false);
-        Info & getInfo(const symbol::Symbol & sym);
-        friend std::wostream & operator<<(std::wostream & out, const DataManager & dm);
-
-        template<typename T>
-        bool getTypes(std::vector<TIType> & out, const T & syms)
+        Block * parent = getCurrent();
+        for (const auto & sym : syms)
+        {
+            tools::SymbolMap<Info>::iterator it;
+            Block * block = parent->getDefBlock(sym, it, false);
+            if (block)
+            {
+                Info & i = it->second;
+                out.emplace_back(i.type.type, i.type.isscalar());
+            }
+            else
             {
-                Block * parent = getCurrent();
-                for (const auto & sym : syms)
-                {
-                    std::map<symbol::Symbol, Info>::iterator it;
-                    Block * block = parent->getDefBlock(sym, it, false);
-                    if (block)
-                    {
-                        Info & i = it->second;
-                        out.emplace_back(i.type.type, i.type.isscalar());
-                    }
-                    else
-                    {
-                        // TODO: get type in Scilab context
-                        return false;
-                    }
-                }
-
-                return true;
+                // TODO: get type in Scilab context
+                return false;
             }
+        }
+
+        return true;
+    }
 
-       static TIType getSymInScilabContext(GVN & gvn, const symbol::Symbol & sym, bool & exists);
-        static TIType getSymInScilabContext(GVN & gvn, const symbol::Symbol & sym, types::InternalType *& pIT);
-        static TIType getSymInScilabContext(GVN & gvn, const symbol::Symbol & sym, bool & exists, types::InternalType *& pIT);
+    static TIType getSymInScilabContext(GVN & gvn, const symbol::Symbol & sym, bool & exists);
+    static TIType getSymInScilabContext(GVN & gvn, const symbol::Symbol & sym, types::InternalType *& pIT);
+    static TIType getSymInScilabContext(GVN & gvn, const symbol::Symbol & sym, bool & exists, types::InternalType *& pIT);
 
-    };
+};
 }
 
 #endif // __DATA_MANAGER_HXX__
index 99b0706..d34bbbc 100644 (file)
 #define __FUNCTIONBLOCK_HXX__
 
 #include <list>
-#include <map>
-#include <set>
 #include <vector>
+#include <set>
+#include <map>
 
+#include "tools.hxx"
 #include "allexp.hxx"
 #include "Block.hxx"
 #include "MacroDef.hxx"
@@ -25,6 +26,7 @@
 #include "TemporaryManager.hxx"
 #include "TITypeSignatureTuple.hxx"
 #include "gvn/ConstraintManager.hxx"
+#include "LoopAnalyzer.hxx"
 
 namespace analysis
 {
@@ -37,15 +39,16 @@ class FunctionBlock : public Block
     std::wstring name;
     std::vector<symbol::Symbol> in;
     std::vector<symbol::Symbol> out;
-    std::set<symbol::Symbol> globals;
+    tools::SymbolOrdSet globals;
     std::vector<std::pair<symbol::Symbol, TypeLocal>> types_in;
     std::vector<std::pair<symbol::Symbol, TypeLocal>> types_out;
-    std::map<symbol::Symbol, std::set<TypeLocal>> locals;
+    tools::SymbolMap<std::set<TypeLocal>> locals;
     std::vector<GVN::Value *> inValues;
     unsigned int lhs;
     unsigned int rhs;
     int maxVarId;
     GVN fgvn;
+    LoopAnalyzer loopAnalyzer;
     ConstraintManager constraintManager;
     TemporaryManager tempManager;
 
@@ -80,19 +83,19 @@ public:
     }
 
     inline const std::vector<std::pair<symbol::Symbol, TypeLocal>> & getTypesIn() const
-       {
-           return types_in;
-       }
+    {
+        return types_in;
+    }
 
     inline const std::vector<std::pair<symbol::Symbol, TypeLocal>> & getTypesOut() const
-       {
-           return types_out;
-       }
+    {
+        return types_out;
+    }
 
-    inline const std::map<symbol::Symbol, std::set<TypeLocal>> & getTypesLocals() const
-       {
-           return locals;
-       }
+    inline const tools::SymbolMap<std::set<TypeLocal>> & getTypesLocals() const
+    {
+        return locals;
+    }
 
     inline int getMaxVarId() const
     {
@@ -116,34 +119,39 @@ public:
     }
 
     inline const std::map<TypeLocal, std::stack<int>> & getTemp() const
-       {
-           return tempManager.getTemp();
-       }
+    {
+        return tempManager.getTemp();
+    }
 
     inline const std::map<TypeLocal, int> getTempCount(int & total) const
-       {
-           int _total = 0;
-           std::map<TypeLocal, int> map;
-           for (const auto & p : getTemp())
-           {
-               _total += p.second.size();
-               map.emplace(p.first, p.second.size());
-           }
-
-           total = _total;
-           
-           return map;
-       }
+    {
+        int _total = 0;
+        std::map<TypeLocal, int> map;
+        for (const auto & p : getTemp())
+        {
+            _total += p.second.size();
+            map.emplace(p.first, p.second.size());
+        }
+
+        total = _total;
+
+        return map;
+    }
+
+    inline const LoopAnalyzer & getLoopAnalyzer() const
+    {
+        return loopAnalyzer;
+    }
 
     void finalize() override;
     void addGlobal(const symbol::Symbol & sym) override;
-    Block * getDefBlock(const symbol::Symbol & sym, std::map<symbol::Symbol, Info>::iterator & it, const bool global) override;
+    Block * getDefBlock(const symbol::Symbol & sym, tools::SymbolMap<Info>::iterator & it, const bool global) override;
     void addLocal(const symbol::Symbol & sym, const TIType & type, const bool isAnInt) override;
     int getTmpId(const TIType & type, const bool isAnInt) override;
     void releaseTmp(const int id) override;
 
     bool addIn(const TITypeSignatureTuple & tuple, const std::vector<GVN::Value *> & values);
-    void setGlobals(const std::set<symbol::Symbol> & v);
+    void setGlobals(const tools::SymbolOrdSet & v);
     //TITypeSignatureTuple getGlobals(std::vector<symbol::Symbol> & v);
     MacroOut getOuts();
     void setInOut(MacroDef * macrodef, const unsigned int rhs, const std::vector<TIType> & _in);
index 66e17bf..6e237d5 100644 (file)
@@ -15,8 +15,9 @@
 
 #include <iostream>
 #include <string>
-#include <set>
 #include <sstream>
+#include <stack>
+#include <vector>
 
 #include "visitor.hxx"
 #include "execvisitor.hxx"
@@ -42,7 +43,7 @@ public:
     virtual ~GlobalsCollector() { }
 
     static void collect(MacroDef & macrodef);
-    const std::set<symbol::Symbol> & getGlobals() const;
+    const tools::SymbolOrdSet & getGlobals() const;
     void print_info();
 
     friend std::wostream & operator<<(std::wostream & out, const GlobalsCollector & gc);
diff --git a/scilab/modules/ast/includes/analysis/data/LoopAnalyzer.hxx b/scilab/modules/ast/includes/analysis/data/LoopAnalyzer.hxx
new file mode 100644 (file)
index 0000000..c54a7a3
--- /dev/null
@@ -0,0 +1,419 @@
+/*
+ *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+ *  Copyright (C) 2014 - Scilab Enterprises - Calixte DENIZET
+ *
+ *  This file must be used under the terms of the CeCILL.
+ *  This source file is licensed as described in the file COPYING, which
+ *  you should have received as part of this distribution.  The terms
+ *  are also available at
+ *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
+ *
+ */
+
+#ifndef __LOOP_ANALYZER_HXX__
+#define __LOOP_ANALYZER_HXX__
+
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <stack>
+#include <unordered_map>
+
+#include "visitor.hxx"
+#include "execvisitor.hxx"
+#include "allexp.hxx"
+#include "allvar.hxx"
+#include "Chrono.hxx"
+#include "tools.hxx"
+
+namespace analysis
+{
+
+class LoopAnalyzer : public ast::Visitor, public Chrono
+{
+    std::unordered_map<ast::Exp *, tools::SymbolSet> assigned;
+    std::unordered_map<ast::Exp *, tools::SymbolSet> inserted;
+    std::unordered_map<ast::Exp *, tools::SymbolSet> shared;
+    std::stack<ast::Exp *> loops;
+    ast::Exp * seq;
+
+public:
+
+    LoopAnalyzer(ast::Exp * _seq) : seq(_seq)
+    {
+        //start_chrono();
+        static_cast<ast::SeqExp *>(seq)->accept(*this);
+        //stop_chrono();
+    }
+
+    virtual ~LoopAnalyzer()
+    {
+    }
+
+    inline bool isAssigned(ast::Exp * e, const symbol::Symbol & sym) const
+    {
+        if (e)
+        {
+            const auto i = assigned.find(e);
+            if (i != assigned.end())
+            {
+                return i->second.find(sym) != i->second.end();
+            }
+        }
+        return false;
+    }
+
+    inline const tools::SymbolSet * getInserted(ast::Exp * e) const
+    {
+        if (e)
+        {
+            const auto i = inserted.find(e);
+            if (i != inserted.end())
+            {
+                return &i->second;
+            }
+        }
+        return nullptr;
+    }
+
+    inline const tools::SymbolSet * getShared(ast::Exp * e) const
+    {
+        if (e)
+        {
+            const auto i = shared.find(e);
+            if (i != shared.end())
+            {
+                return &i->second;
+            }
+        }
+        return nullptr;
+    }
+
+    friend std::wostream & operator<<(std::wostream & out, const LoopAnalyzer & la)
+    {
+        if (!la.assigned.empty())
+        {
+            out << L" Assigned:\n";
+            for (const auto & p : la.assigned)
+            {
+                out << L"  -Loop at " << p.first->getLocation().getLocationString() << L": ";
+                tools::printSet(p.second, out);
+                out << L"\n";
+            }
+        }
+
+        if (!la.inserted.empty())
+        {
+            out << L" Inserted:\n";
+            for (const auto & p : la.inserted)
+            {
+                out << L"  -Loop at " << p.first->getLocation().getLocationString() << L": ";
+                tools::printSet(p.second, out);
+                out << L"\n";
+            }
+        }
+
+        if (!la.shared.empty())
+        {
+            out << L" Shared:\n";
+            for (const auto & p : la.shared)
+            {
+                out << L"  -Loop at " << p.first->getLocation().getLocationString() << L": ";
+                tools::printSet(p.second, out);
+                out << L"\n";
+            }
+        }
+
+        return out;
+    }
+
+    inline void print_info()
+    {
+        std::wcerr << L"Loop analyze: " << *static_cast<Chrono *>(this) << std::endl
+                   << *this << std::endl;
+    }
+
+private:
+
+    inline void emplace(std::unordered_map<ast::Exp *, tools::SymbolSet> & map, const symbol::Symbol & sym)
+    {
+        ast::Exp * loop = loops.top();
+        auto i = map.find(loop);
+        if (i == map.end())
+        {
+            i = map.emplace(loop, tools::SymbolSet()).first;
+        }
+        i->second.emplace(sym);
+    }
+
+    inline void pushAssigned()
+    {
+        ast::Exp * last = loops.top();
+        loops.pop();
+
+        if (!loops.empty())
+        {
+            ast::Exp * penult = loops.top();
+            const auto i = assigned.find(last);
+            if (i != assigned.end())
+            {
+                const auto j = assigned.find(penult);
+                if (j == assigned.end())
+                {
+                    assigned.emplace(penult, i->second);
+                }
+                else
+                {
+                    j->second.insert(i->second.begin(), i->second.end());
+                }
+            }
+        }
+    }
+
+    void visit(ast::SimpleVar & e)
+    {
+    }
+
+    void visit(ast::DollarVar & e)
+    {
+    }
+
+    void visit(ast::ColonVar & e)
+    {
+    }
+
+    void visit(ast::ArrayListVar & e)
+    {
+    }
+
+    void visit(ast::DoubleExp & e)
+    {
+    }
+
+    void visit(ast::BoolExp & e)
+    {
+    }
+
+    void visit(ast::StringExp & e)
+    {
+    }
+
+    void visit(ast::CommentExp & e)
+    {
+    }
+
+    void visit(ast::NilExp & e)
+    {
+    }
+
+    void visit(ast::CallExp & e)
+    {
+    }
+
+    void visit(ast::CellCallExp & e)
+    {
+    }
+
+    void visit(ast::OpExp & e)
+    {
+    }
+
+    void visit(ast::LogicalOpExp & e)
+    {
+    }
+
+    void visit(ast::AssignExp & e)
+    {
+        if (e.getLeftExp().isSimpleVar())
+        {
+            // A = ....
+            const symbol::Symbol & Lsym = static_cast<ast::SimpleVar &>(e.getLeftExp()).getSymbol();
+            emplace(assigned, Lsym);
+            if (e.getRightExp().isSimpleVar())
+            {
+                const symbol::Symbol & Rsym = static_cast<ast::SimpleVar &>(e.getRightExp()).getSymbol();
+                emplace(shared, Lsym);
+                emplace(shared, Rsym);
+            }
+        }
+        else if (e.getLeftExp().isCallExp())
+        {
+            // A(...) = ...
+            ast::CallExp & ce = static_cast<ast::CallExp &>(e.getLeftExp());
+            if (ce.getName().isSimpleVar())
+            {
+                const symbol::Symbol & Lsym = static_cast<ast::SimpleVar &>(ce.getName()).getSymbol();
+                emplace(inserted, Lsym);
+                emplace(assigned, Lsym);
+            }
+        }
+        else if (e.getLeftExp().isAssignListExp())
+        {
+            // [A, ...] =
+            ast::AssignListExp & ale = static_cast<ast::AssignListExp &>(e.getLeftExp());
+            for (const auto re : ale.getExps())
+            {
+                if (re->isSimpleVar())
+                {
+                    const symbol::Symbol & Lsym = static_cast<const ast::SimpleVar *>(re)->getSymbol();
+                    emplace(assigned, Lsym);
+                }
+            }
+        }
+    }
+
+    void visit(ast::IfExp & e)
+    {
+        e.getThen().accept(*this);
+        if (e.hasElse())
+        {
+            e.getElse().accept(*this);
+        }
+    }
+
+    void visit(ast::WhileExp & e)
+    {
+        loops.push(&e);
+        e.getBody().accept(*this);
+
+        // pushAssigned pops loops
+        pushAssigned();
+    }
+
+    void visit(ast::ForExp & e)
+    {
+        loops.push(&e);
+        e.getVardec().accept(*this);
+        e.getBody().accept(*this);
+        pushAssigned();
+    }
+
+    void visit(ast::BreakExp & e)
+    {
+    }
+
+    void visit(ast::ContinueExp & e)
+    {
+    }
+
+    void visit(ast::TryCatchExp & e)
+    {
+        e.getTry().accept(*this);
+        e.getCatch().accept(*this);
+    }
+
+    void visit(ast::SelectExp & e)
+    {
+        e.getSelect()->accept(*this);
+        for (auto _e : e.getCases())
+        {
+            _e->accept(*this);
+        }
+        if (ast::Exp * def = e.getDefaultCase())
+        {
+            def->accept(*this);
+        }
+    }
+
+    void visit(ast::CaseExp & e)
+    {
+        e.getBody()->accept(*this);
+    }
+
+    void visit(ast::ReturnExp & e)
+    {
+    }
+
+    void visit(ast::FieldExp & e)
+    {
+    }
+
+    void visit(ast::NotExp & e)
+    {
+    }
+
+    void visit(ast::TransposeExp & e)
+    {
+    }
+
+    void visit(ast::MatrixExp & e)
+    {
+    }
+
+    void visit(ast::MatrixLineExp & e)
+    {
+    }
+
+    void visit(ast::CellExp & e)
+    {
+    }
+
+    void visit(ast::SeqExp & e)
+    {
+        if (loops.empty())
+        {
+            for (auto _e : e.getExps())
+            {
+                if (_e->isForExp() || _e->isWhileExp())
+                {
+                    _e->accept(*this);
+                }
+            }
+        }
+        else
+        {
+            for (auto _e : e.getExps())
+            {
+                _e->accept(*this);
+            }
+        }
+    }
+
+    void visit(ast::ArrayListExp & e)
+    {
+    }
+
+    void visit(ast::AssignListExp & e)
+    {
+    }
+
+    void visit(ast::VarDec & e)
+    {
+        emplace(assigned, e.getSymbol());
+    }
+
+    void visit(ast::FunctionDec & e)
+    {
+    }
+
+    void visit(ast::ListExp & e)
+    {
+    }
+
+    void visit(ast::OptimizedExp & e)
+    {
+    }
+
+    void visit(ast::MemfillExp & e)
+    {
+    }
+
+    void visit(ast::DAXPYExp & e)
+    {
+    }
+
+    void visit(ast::IntSelectExp & e)
+    {
+        visit(static_cast<ast::SelectExp &>(e));
+    }
+
+    void visit(ast::StringSelectExp & e)
+    {
+        visit(static_cast<ast::SelectExp &>(e));
+    }
+};
+
+} // namespace analysis
+
+#endif // __LOOP_ANALYZER_HXX__
+
index c701606..2591070 100644 (file)
 #ifndef __LOOPBLOCK_HXX__
 #define __LOOPBLOCK_HXX__
 
+#include <unordered_map>
+
 #include "Block.hxx"
+#include "tools.hxx"
 
 namespace analysis
 {
 
+class LoopAnalyzer;
+
 class LoopBlockHead : public Block
 {
     /*
@@ -40,7 +45,7 @@ class LoopBlockHead : public Block
 
       The problem is that in the most of the cases loops should have a lot of iterations so we can suppose with a
       good probability that inferred types after the loop should be ones guessed after two iterations.
-      */
+    */
 
 public:
 
@@ -51,13 +56,22 @@ public:
         return blocks.front();
     }
 
+    inline Block * getSecondBlock()
+    {
+        return blocks.back();
+    }
+
     Block * addBlock(const unsigned int id, BlockKind kind, ast::Exp * exp) override;
     void finalize() override;
 };
 
 class LoopBlock : public Block
 {
+
+    friend class LoopBlockHead;
+
     const bool first;
+    std::unordered_map<ast::Exp *, symbol::Symbol> clonedSym;
 
 public:
     LoopBlock(const unsigned int id, Block * parent, ast::Exp * exp, const bool _first) : Block(id, parent, exp), first(_first) { }
@@ -68,8 +82,9 @@ public:
     }
 
     bool requiresAnotherTrip() override;
-    Block * getDefBlock(const symbol::Symbol & sym, std::map<symbol::Symbol, Info>::iterator & it, const bool global) override;
+    Block * getDefBlock(const symbol::Symbol & sym, tools::SymbolMap<Info>::iterator & it, const bool global) override;
     Info & getInfo(const symbol::Symbol & sym) override;
+    void clone(const symbol::Symbol & sym, ast::Exp * exp) override;
     void finalize() override;
 };
 
index 706cfa9..ef3e64c 100644 (file)
@@ -23,6 +23,7 @@
 #include "allvar.hxx"
 #include "alltypes.hxx"
 #include "symbol.hxx"
+#include "tools.hxx"
 
 namespace analysis
 {
@@ -31,12 +32,12 @@ class MacroDef
 {
 
 protected:
-    
+
     const unsigned int lhs;
     const unsigned int rhs;
     ast::Exp * const original;
 
-    std::set<symbol::Symbol> globals;
+    tools::SymbolOrdSet globals;
 
 public:
 
@@ -60,16 +61,16 @@ public:
     }
 
     inline ast::Exp * getOriginal() const
-       {
-           return original;
-       }
-    
-    inline std::set<symbol::Symbol> & getGlobals()
+    {
+        return original;
+    }
+
+    inline tools::SymbolOrdSet & getGlobals()
     {
         return globals;
     }
 
-    inline const std::set<symbol::Symbol> & getGlobals() const
+    inline const tools::SymbolOrdSet & getGlobals() const
     {
         return globals;
     }
@@ -103,17 +104,17 @@ class ExistingMacroDef : public MacroDef
     ast::SeqExp * se;
     std::vector<symbol::Symbol> inputs;
     std::vector<symbol::Symbol> outputs;
-    
+
 public:
 
     ExistingMacroDef(types::Macro & _macro);
     ExistingMacroDef(const ExistingMacroDef & emd);
 
     ~ExistingMacroDef()
-       {
-           delete se;
-       }
-    
+    {
+        delete se;
+    }
+
     ast::SeqExp & getBody();
     const std::wstring & getName();
     std::vector<symbol::Symbol> getIn();
@@ -130,9 +131,9 @@ public:
     DeclaredMacroDef(ast::FunctionDec * const _dec);
 
     ~DeclaredMacroDef()
-       {
-           delete dec;
-       }
+    {
+        delete dec;
+    }
 
     ast::SeqExp & getBody();
     const std::wstring & getName();
index 63d1163..f553bfb 100644 (file)
@@ -20,6 +20,8 @@
 #include <limits>
 #include <map>
 #include <set>
+#include <unordered_map>
+#include <unordered_set>
 
 #ifdef _MSC_VER
 #include "stdint.h"
 #endif
 
 #include "core_math.h"
+#include "symbol.hxx"
 
 namespace analysis
 {
 
-    namespace tools
-    {
-               
+namespace tools
+{
+
 #ifdef _MSC_VER
-        inline static double trunc(const double x)
-        {
-            return x > 0 ? floor(x) : ceil(x);
-        }
+inline static double trunc(const double x)
+{
+    return x > 0 ? floor(x) : ceil(x);
+}
 
-        inline static uint32_t clz(const uint32_t x)
-        {
-            unsigned long r = 0;
-            _BitScanForward(&r, x);
-            return r;
-        }
+inline static uint32_t clz(const uint32_t x)
+{
+    unsigned long r = 0;
+    _BitScanForward(&r, x);
+    return r;
+}
 
-        inline static uint32_t clzll(const uint64_t x)
-        {
+inline static uint32_t clzll(const uint64_t x)
+{
 #ifdef _WIN64
-            unsigned long r = 0;
-            _BitScanForward64(&r, x);
-            return r;
+    unsigned long r = 0;
+    _BitScanForward64(&r, x);
+    return r;
 #else
-            const uint32_t u32 = x >> 32;
-           if (u32)
-           {
-               return clz(u32);
-           }
-           return 32 + clz(x & 0xFFFFFFFFUL);
+    const uint32_t u32 = x >> 32;
+    if (u32)
+    {
+        return clz(u32);
+    }
+    return 32 + clz(x & 0xFFFFFFFFUL);
 #endif
-        }
+}
 #else
-        inline static double trunc(const double x)
-        {
+inline static double trunc(const double x)
+{
 #ifdef __APPLE__
-            // Needed for compilation with GCC 4.8.2
-            return x > 0 ? floor(x) : ceil(x);
+    // Needed for compilation with GCC 4.8.2
+    return x > 0 ? floor(x) : ceil(x);
 #else
-            return std::trunc(x);
+    return std::trunc(x);
 #endif
-        }
+}
 
-        inline static uint32_t clz(const uint32_t x)
-        {
-            return x ? __builtin_clz(x) : 32;
-        }
+inline static uint32_t clz(const uint32_t x)
+{
+    return x ? __builtin_clz(x) : 32;
+}
 
-        inline static uint32_t clzll(const uint64_t x)
-        {
-            return x ? __builtin_clzll(x) : 64;
-        }
+inline static uint32_t clzll(const uint64_t x)
+{
+    return x ? __builtin_clzll(x) : 64;
+}
 #endif
 
-        inline static double NaN()
-        {
-            return std::numeric_limits<double>::quiet_NaN();
-        }
+inline static double NaN()
+{
+    return std::numeric_limits<double>::quiet_NaN();
+}
 
-        inline static bool isNaN(const double x)
-        {
-            return ISNAN(x) != 0;
-        }
+inline static bool isNaN(const double x)
+{
+    return ISNAN(x) != 0;
+}
 
-        inline static bool isFinite(const double x)
-        {
-            return finite(x) != 0;
-        }
+inline static bool isFinite(const double x)
+{
+    return finite(x) != 0;
+}
 
-        inline static bool isInfinite(const double x)
-        {
-            return !isFinite(x);
-        }
+inline static bool isInfinite(const double x)
+{
+    return !isFinite(x);
+}
 
-        enum IntType { NOTANINT, SIGNED, UNSIGNED };
+enum IntType { NOTANINT, SIGNED, UNSIGNED };
 
-        inline static IntType getIntType(const double x)
+inline static IntType getIntType(const double x)
+{
+    if (x == trunc(x))
+    {
+        if (x >= 0)
         {
-            if (x == trunc(x))
+            if (x <= (double)std::numeric_limits<uint64_t>::max())
             {
-                if (x >= 0)
-                {
-                    if (x <= (double)std::numeric_limits<uint64_t>::max())
-                    {
-                        return UNSIGNED;
-                    }
-                }
-                else if (x >= (double)std::numeric_limits<int64_t>::min())
-                {
-                    return SIGNED;
-                }
+                return UNSIGNED;
             }
-
-            return NOTANINT;
         }
-
-       template<typename T>
-        inline static bool asInteger(const double x, T & ival)
+        else if (x >= (double)std::numeric_limits<int64_t>::min())
         {
-            if (x == trunc(x))
-            {
-                if (x >= 0)
-                {
-                    if (x <= (double)std::numeric_limits<T>::max())
-                    {
-                        ival = (T)x;
-                        return true;
-                    }
-                }
-                else if (x >= (double)std::numeric_limits<T>::min())
-                {
-                    ival = (T)x;
-                    return true;
-                }
-            }
-
-            return false;
+            return SIGNED;
         }
+    }
 
-        inline static bool isAnInt(const double x)
-        {
-            return getIntType(x) != NOTANINT;
-        }
+    return NOTANINT;
+}
 
-        template<typename T>
-        inline static T cast(const double x)
+template<typename T>
+inline static bool asInteger(const double x, T & ival)
+{
+    if (x == trunc(x))
+    {
+        if (x >= 0)
         {
-            if (x < static_cast<double>(std::numeric_limits<T>::max()))
+            if (x <= (double)std::numeric_limits<T>::max())
             {
-                if (x > static_cast<double>(std::numeric_limits<T>::min()))
-                {
-                    return static_cast<T>(x);
-                }
-                else
-                {
-                    return std::numeric_limits<T>::min();
-                }
-            }
-            else
-            {
-                return std::numeric_limits<T>::max();
+                ival = (T)x;
+                return true;
             }
         }
-
-       template<typename T>
-       inline static T powui(T x, uint64_t n)
-       {
-           T p = x;
-           T y = (n & 1) ? x : 1;
-           
-           while (n >>= 1)
-           {
-               p *= p;
-               if (n & 1)
-               {
-                   y *= p;
-               }
-           }
-           
-           return y;
-       }
-
-        inline std::wostream & operator<<(std::wostream & out, const IntType & it)
+        else if (x >= (double)std::numeric_limits<T>::min())
         {
-            switch (it)
-            {
-            case IntType::NOTANINT :
-                out << L"NAI";
-                break;
-            case IntType::SIGNED :
-                out << L"S";
-                break;
-            case IntType::UNSIGNED :
-                out << L"U";
-                break;
-            }
-            return out;
+            ival = (T)x;
+            return true;
         }
+    }
 
-        template<typename T>
-        inline static unsigned char popcount(const T x)
+    return false;
+}
+
+inline static bool isAnInt(const double x)
+{
+    return getIntType(x) != NOTANINT;
+}
+
+template<typename T>
+inline static T cast(const double x)
+{
+    if (x < static_cast<double>(std::numeric_limits<T>::max()))
+    {
+        if (x > static_cast<double>(std::numeric_limits<T>::min()))
         {
-            return std::bitset<sizeof(T)>(x).count();
+            return static_cast<T>(x);
         }
-
-        inline static unsigned char log2(const unsigned int x)
+        else
         {
-            return (unsigned char)((sizeof(unsigned int) << 3) - clz(x) - 1);
+            return std::numeric_limits<T>::min();
         }
+    }
+    else
+    {
+        return std::numeric_limits<T>::max();
+    }
+}
 
-        inline static unsigned char log2(const unsigned long long x)
+template<typename T>
+inline static T powui(T x, uint64_t n)
+{
+    T p = x;
+    T y = (n & 1) ? x : 1;
+
+    while (n >>= 1)
+    {
+        p *= p;
+        if (n & 1)
         {
-            return (unsigned char)((sizeof(unsigned long long) << 3) - clzll(x) - 1);
+            y *= p;
         }
+    }
+
+    return y;
+}
+
+inline std::wostream & operator<<(std::wostream & out, const IntType & it)
+{
+    switch (it)
+    {
+        case IntType::NOTANINT :
+            out << L"NAI";
+            break;
+        case IntType::SIGNED :
+            out << L"S";
+            break;
+        case IntType::UNSIGNED :
+            out << L"U";
+            break;
+    }
+    return out;
+}
+
+template<typename T>
+inline static unsigned char popcount(const T x)
+{
+    return std::bitset<sizeof(T)>(x).count();
+}
+
+inline static unsigned char log2(const unsigned int x)
+{
+    return (unsigned char)((sizeof(unsigned int) << 3) - clz(x) - 1);
+}
 
-        template<typename T>
-        static void printSet(const T & set, std::wostream & out)
+inline static unsigned char log2(const unsigned long long x)
+{
+    return (unsigned char)((sizeof(unsigned long long) << 3) - clzll(x) - 1);
+}
+
+template<typename T>
+static void printSet(const T & set, std::wostream & out)
+{
+    if (set.empty())
+    {
+        out << L"{}";
+    }
+    else
+    {
+        out << L"{";
+        for (typename T::const_iterator i = set.begin(); i != set.end(); ++i)
         {
-            if (set.empty())
+            if (std::next(i) == set.end())
             {
-                out << L"{}";
+                out << *i << L"}";
             }
             else
             {
-                out << L"{";
-                typename T::const_iterator e = std::prev(set.end());
-                for (typename T::const_iterator i = set.begin(); i != e; ++i)
-                {
-                    out << *i << L",";
-                }
-                out << *e << L"}";
+                out << *i << L",";
             }
         }
+    }
+}
 
-        template<typename T>
-        static void printMapInfo(std::wostream & out, const T & map, const bool show_collisions = false)
+template<typename T>
+static void printMap(const T & map, std::wostream & out)
+{
+    if (map.empty())
+    {
+        out << L"{}";
+    }
+    else
+    {
+        out << L"{";
+        for (typename T::const_iterator i = map.begin(); i != map.end(); ++i)
         {
-            double mean = 0;
-            double variance = 0;
-            double count = map.bucket_count();
-            unsigned int empty_bucket_count = 0;
-            unsigned int collision_count = 0;
-
-            out << L"Map size: " << map.size() << std::endl;
-            out << L"Number of buckets: " << count << std::endl;
-
-            for (unsigned int i = 0; i < map.bucket_count(); ++i)
+            out << i->first << L" -> " << i->second;
+            if (std::next(i) == map.end())
             {
-                if (unsigned int s = map.bucket_size(i))
-                {
-                    mean += s;
-                    if (s > 1)
-                    {
-                        ++collision_count;
-                    }
-                }
-                else
-                {
-                    ++empty_bucket_count;
-                }
+                out << L"}";
             }
-            mean /= count;
-
-            for (unsigned int i = 0; i < map.bucket_count(); ++i)
+            else
             {
-                const unsigned int s = map.bucket_size(i);
-                variance += (mean - s) * (mean - s);
+                out << L",";
             }
-            variance /= count;
+        }
+    }
+}
 
-            out << L"Number of elements by buckets: mean=" << mean << L", sigma=" << std::sqrt(variance) << std::endl;
-            out << L"Number of empty buckets: " << empty_bucket_count << std::endl;
-            out << L"Number of collisions: " << collision_count << std::endl;
+template<typename T>
+static void printMapInfo(std::wostream & out, const T & map, const bool show_collisions = false)
+{
+    double mean = 0;
+    double variance = 0;
+    double count = map.bucket_count();
+    unsigned int empty_bucket_count = 0;
+    unsigned int collision_count = 0;
+
+    out << L"Map size: " << map.size() << std::endl;
+    out << L"Number of buckets: " << count << std::endl;
 
-            if (show_collisions)
+    for (unsigned int i = 0; i < map.bucket_count(); ++i)
+    {
+        if (unsigned int s = map.bucket_size(i))
+        {
+            mean += s;
+            if (s > 1)
             {
-                std::multimap<unsigned int, typename T::key_type> collisions;
-                for (const auto & p : map)
-                {
-                    collisions.emplace(map.bucket(p.first), p.first);
-                }
-
-                for (const auto & p : collisions)
-                {
-                    out << L"Bucket " << p.first << L": " << p.second << L", hash=" << (typename T::hasher()(p.second)) << std::endl;
-                }
+                ++collision_count;
             }
         }
+        else
+        {
+            ++empty_bucket_count;
+        }
+    }
+    mean /= count;
+
+    for (unsigned int i = 0; i < map.bucket_count(); ++i)
+    {
+        const unsigned int s = map.bucket_size(i);
+        variance += (mean - s) * (mean - s);
+    }
+    variance /= count;
+
+    out << L"Number of elements by buckets: mean=" << mean << L", sigma=" << std::sqrt(variance) << std::endl;
+    out << L"Number of empty buckets: " << empty_bucket_count << std::endl;
+    out << L"Number of collisions: " << collision_count << std::endl;
 
-        inline static std::size_t hash_combine(const std::size_t seed)
+    if (show_collisions)
+    {
+        std::multimap<unsigned int, typename T::key_type> collisions;
+        for (const auto & p : map)
         {
-            return seed;
+            collisions.emplace(map.bucket(p.first), p.first);
         }
 
-        template<typename... Args>
-        inline static std::size_t hash_combine(const std::size_t seed, Args... args)
+        for (const auto & p : collisions)
         {
-            // it is the way Boost has implemented hash_combine:
-            // http://www.boost.org/doc/libs/1_35_0/doc/html/boost/hash_combine_id241013.html
-            return seed ^ (hash_combine(args...) + 0x9e3779b9 + (seed << 6) + (seed >> 2));
+            out << L"Bucket " << p.first << L": " << p.second << L", hash=" << (typename T::hasher()(p.second)) << std::endl;
         }
+    }
+}
+
+inline static std::size_t hash_combine(const std::size_t seed)
+{
+    return seed;
+}
+
+template<typename... Args>
+inline static std::size_t hash_combine(const std::size_t seed, Args... args)
+{
+    // it is the way Boost has implemented hash_combine:
+    // http://www.boost.org/doc/libs/1_35_0/doc/html/boost/hash_combine_id241013.html
+    return seed ^ (hash_combine(args...) + 0x9e3779b9 + (seed << 6) + (seed >> 2));
+}
+
+struct HashSymbol
+{
+    inline std::size_t operator()(const symbol::Symbol & sym) const
+    {
+        return std::hash<std::wstring>()(sym.getName());
+    }
+};
+
+struct EqSymbol
+{
+    inline bool operator()(const symbol::Symbol & L, const symbol::Symbol & R) const
+    {
+        return L == R;
+    }
+};
+
+typedef std::set<symbol::Symbol> SymbolOrdSet;
+typedef std::unordered_set<symbol::Symbol, HashSymbol> SymbolSet;
+template<typename T>
+using SymbolMap = std::unordered_map<symbol::Symbol, T, HashSymbol, EqSymbol>;
 
-    } // namespace tools
+} // namespace tools
 
 } // namespace analysis
 
index d6bd3d6..f03f162 100644 (file)
@@ -99,17 +99,12 @@ public:
 
     const analysis::Decorator & getDecorator() const
     {
-       return decorator;
+        return decorator;
     }
 
     analysis::Decorator & getDecorator()
     {
-       return decorator;
-    }
-
-    void setDecorator(analysis::Decorator & _decorator)
-    {
-       decorator = _decorator;
+        return decorator;
     }
 
 private:
index 6788694..d09ba55 100644 (file)
@@ -96,6 +96,11 @@ public:
         return MAPINTSELECTEXP;
     }
 
+    inline const std::unordered_map<int64_t, Exp *> & getTable() const
+    {
+        return map;
+    }
+
 private:
 
     std::unordered_map<int64_t, Exp *> map;
index 0381164..a4a09e6 100644 (file)
@@ -83,6 +83,11 @@ public:
         return SMALLINTSELECTEXP;
     }
 
+    inline const std::vector<int64_t> & getTable() const
+    {
+        return table;
+    }
+
 private:
 
     std::vector<int64_t> table;
index 4eea46a..a80bf2d 100644 (file)
 namespace analysis
 {
 
-    Block::Block(DataManager * _dm) : dm(_dm), parent(nullptr), exp(nullptr), gvn(&dm->getDefaultGVN()), isReturn(false), id(0) { }
+Block::Block(DataManager * _dm) : dm(_dm), parent(nullptr), exp(nullptr), gvn(&dm->getDefaultGVN()), isReturn(false), id(0) { }
 
-    Block::~Block()
+Block::~Block()
+{
+    std::for_each(blocks.begin(), blocks.end(), [](Block * b)
     {
-        std::for_each(blocks.begin(), blocks.end(), [](Block * b)
-                      {
-                          delete b;
-                      });
-    }
+        delete b;
+    });
+}
+
+void Block::addGlobal(const symbol::Symbol & sym)
+{
+    dm->addGlobal(sym);
+}
+
+GVN & Block::getGVN()
+{
+    return *gvn;
+}
 
-    void Block::addGlobal(const symbol::Symbol & sym)
+Info & Block::setDefaultData(const symbol::Symbol & sym)
+{
+    Info & i = addSym(sym, new Data(false, sym));
+    i.local = Info::Local::INFO_FALSE;
+    i.type = DataManager::getSymInScilabContext(getGVN(), sym, i.exists);
+    addGlobal(sym);
+    dm->registerData(i.data);//, __LINE__, __FILE__);
+
+    return i;
+}
+
+void Block::clone(Info & info, const symbol::Symbol & sym, ast::Exp * exp)
+{
+    if (!info.data->hasOneOwner())
     {
-        dm->addGlobal(sym);
+        // data is shared between several symbols => we need to clone it
+        info.data->rem(sym);
+        info.data = new Data(info.isknown(), sym);
+        dm->registerData(info.data);//, __LINE__, __FILE__);
+        clone(sym, exp);
+        exp->getDecorator().cloneData = true;
     }
+}
 
-    GVN & Block::getGVN()
+void Block::clone(const symbol::Symbol & sym, ast::Exp * exp)
+{
+    if (parent)
     {
-       return *gvn;
+        parent->clone(sym, exp);
     }
-    
-    Info & Block::setDefaultData(const symbol::Symbol & sym)
+    else
     {
-        Info & i = addSym(sym, new Data(false, sym));
-        i.local = Info::Local::INFO_FALSE;
-        i.type = DataManager::getSymInScilabContext(getGVN(), sym, i.exists);
-        addGlobal(sym);
-        dm->registerData(i.data);//, __LINE__, __FILE__);
-
-        return i;
+        exp->getDecorator().addClone(sym);
     }
+}
 
-    Info & Block::putSymsInScope(const symbol::Symbol & sym, Block * block, Info & info)
+Info & Block::putSymsInScope(const symbol::Symbol & sym, Block * block, Info & info)
+{
+    // We put the sym (which is defined in block) in this block and pull all its companions too.
+    Info & i = addSym(sym, info);
+    Data * data = i.data;
+    // emplace called the Info's copy ctor so a new Data has been allocated
+    dm->registerData(data);//, __LINE__, __FILE__);
+    // We put all the shared syms in this scope
+    if (!data->hasOneOwner())
     {
-        // We put the sym (which is defined in block) in this block and pull all its companions too.
-        Info & i = addSym(sym, info);
-        Data * data = i.data;
-        // emplace called the Info's copy ctor so a new Data has been allocated
-        dm->registerData(data);//, __LINE__, __FILE__);
-        // We put all the shared syms in this scope
-        if (!data->hasOneOwner())
+        for (const auto & _sym : data->sharedSyms)
         {
-            for (const auto & _sym : data->sharedSyms)
+            if (sym != _sym)
             {
-                if (sym != _sym)
-                {
-                    Info & _i = block->symMap.find(_sym)->second;
-                    Data * old = _i.data;
-                    // we set _i.data to nullptr to avoid the data copy when cloning _i
-                    _i.data = nullptr;
-                    addSym(_sym, _i).data = data;
-                    _i.data = old;
-                }
+                Info & _i = block->symMap.find(_sym)->second;
+                Data * old = _i.data;
+                // we set _i.data to nullptr to avoid the data copy when cloning _i
+                _i.data = nullptr;
+                addSym(_sym, _i).data = data;
+                _i.data = old;
             }
         }
-
-        return i;
     }
 
-    Info & Block::putSymsInScope(const symbol::Symbol & sym)
-    {
-        std::map<symbol::Symbol, Info>::iterator it;
-       Block * block = getDefBlock(sym, it, false);
-        if (!block)
-        {
-            Info & info = dm->root->setDefaultData(sym);
-            block = dm->root;
-           if (block != this)
-           {
-               return putSymsInScope(sym, block, info);
-           }
-           return info;
-        }
+    return i;
+}
 
+Info & Block::putSymsInScope(const symbol::Symbol & sym)
+{
+    tools::SymbolMap<Info>::iterator it;
+    Block * block = getDefBlock(sym, it, false);
+    if (!block)
+    {
+        Info & info = dm->root->setDefaultData(sym);
+        block = dm->root;
         if (block != this)
         {
-            return putSymsInScope(sym, block, it->second);
+            return putSymsInScope(sym, block, info);
         }
-
-        return it->second;
+        return info;
     }
 
-    Block * Block::getDefBlock(const symbol::Symbol & sym, std::map<symbol::Symbol, Info>::iterator & it, const bool global)
+    if (block != this)
     {
-        it = symMap.find(sym);
-        if (it != symMap.end())
-        {
-            return this;
-        }
-        else if (parent)
-        {
-            // search sym in the previous block
-            return parent->getDefBlock(sym, it, global);
-        }
-
-        return nullptr;
+        return putSymsInScope(sym, block, it->second);
     }
 
-    Info & Block::getInfo(const symbol::Symbol & sym)
+    return it->second;
+}
+
+Block * Block::getDefBlock(const symbol::Symbol & sym, tools::SymbolMap<Info>::iterator & it, const bool global)
+{
+    it = symMap.find(sym);
+    if (it != symMap.end())
     {
-        std::map<symbol::Symbol, Info>::iterator i = symMap.find(sym);
-        if (i != symMap.end())
-        {
-            // The sym has been already used in this block
-            return i->second;
-        }
-        else if (parent)
-        {
-            // search sym in the previous block
-            return parent->getInfo(sym);
-        }
-        else
-        {
-            // We are in the root block (parent == nullptr) and the sym doesn't exist here
-            // so we can presumed that it exists in the previous scope
-            return setDefaultData(sym);
-        }
+        return this;
     }
-
-    Info & Block::addRead(const symbol::Symbol & sym, ast::Exp * exp)
+    else if (parent)
     {
-        /* READ:
-           - no type modification
-           - no refcount modification
-        */
-        Info & info = getInfo(sym);
-        info.R = true;
+        // search sym in the previous block
+        return parent->getDefBlock(sym, it, global);
+    }
 
-        return info;
+    return nullptr;
+}
+
+Info & Block::getInfo(const symbol::Symbol & sym)
+{
+    tools::SymbolMap<Info>::iterator i = symMap.find(sym);
+    if (i != symMap.end())
+    {
+        // The sym has been already used in this block
+        return i->second;
+    }
+    else if (parent)
+    {
+        // search sym in the previous block
+        return parent->getInfo(sym);
     }
+    else
+    {
+        // We are in the root block (parent == nullptr) and the sym doesn't exist here
+        // so we can presumed that it exists in the previous scope
+        return setDefaultData(sym);
+    }
+}
+
+Info & Block::addRead(const symbol::Symbol & sym, ast::Exp * exp)
+{
+    /* READ:
+       - no type modification
+       - no refcount modification
+    */
+    Info & info = getInfo(sym);
+    info.R = true;
+
+    return info;
+}
 
-    Info & Block::addWrite(const symbol::Symbol & sym, const TIType & Rtype, ast::Exp * exp)
+Info & Block::addWrite(const symbol::Symbol & sym, const TIType & Rtype, ast::Exp * exp)
+{
+    /* WRITE:
+       - TODO: if x is scalar and x(2)=3 then x is a matrix !
+       - type can be modified: a=1:3; a(1)=%i or $; a is typed complex or polynomial
+       - if associated data is shared then we need to clone it
+    */
+    Info & info = putSymsInScope(sym);
+    if (info.exists)
     {
-        /* WRITE:
-           - TODO: if x is scalar and x(2)=3 then x is a matrix !
-           - type can be modified: a=1:3; a(1)=%i or $; a is typed complex or polynomial
-           - if associated data is shared then we need to clone it
-        */
-        Info & info = putSymsInScope(sym);
-        if (info.exists)
+        if (info.type.type == TIType::Type::DOUBLE)
         {
-            if (info.type.type == TIType::Type::DOUBLE)
+            if (Rtype.type == TIType::Type::COMPLEX)
             {
-                if (Rtype.type == TIType::Type::COMPLEX)
-                {
-                    info.type.type = TIType::Type::COMPLEX;
-                }
-                else if (Rtype.type == TIType::Type::POLYNOMIAL)
-                {
-                    info.type.type = TIType::Type::POLYNOMIAL;
-                }
+                info.type.type = TIType::Type::COMPLEX;
+            }
+            else if (Rtype.type == TIType::Type::POLYNOMIAL)
+            {
+                info.type.type = TIType::Type::POLYNOMIAL;
             }
         }
-        else
-        {
-            info.type = Rtype;
-            info.exists = true;
-        }
-
-        if (!info.data->hasOneOwner())
-        {
-            // data is shared between several symbols => we need to clone it
-            info.data->rem(sym);
-            info.data = new Data(info.isknown(), sym);
-            dm->registerData(info.data);//, __LINE__, __FILE__);
-        }
-        info.W = true;
-
-        return info;
     }
-
-    void Block::addLocal(const symbol::Symbol & sym, const TIType & type, const bool isAnInt)
+    else
     {
-       if (parent)
-       {
-           parent->addLocal(sym, type, isAnInt);
-       }
+        info.type = Rtype;
+        info.exists = true;
     }
 
-    int Block::getTmpId(const TIType & type, const bool isAnInt)
-    {
-       if (parent)
-       {
-           return parent->getTmpId(type, isAnInt);
-       }
+    clone(info, sym, exp);
+    info.W = true;
 
-       return -1;
-    }
-    
-    void Block::releaseTmp(const int id)
+    return info;
+}
+
+void Block::addLocal(const symbol::Symbol & sym, const TIType & type, const bool isAnInt)
+{
+    if (parent)
     {
-       if (parent)
-       {
-           parent->releaseTmp(id);
-       }
+        parent->addLocal(sym, type, isAnInt);
     }
+}
 
-    Info & Block::addDefine(const symbol::Symbol & sym, const TIType & Rtype, const bool isIntIterator, ast::Exp * exp)
+int Block::getTmpId(const TIType & type, const bool isAnInt)
+{
+    if (parent)
     {
-        /* DEFINE:
-           - if associated data is shared then we need to clone it
-        */
-       addLocal(sym, Rtype, isIntIterator);
-        Info & info = putAndClear(sym, exp);
-        info.cleared = false;
-        info.data = new Data(true, sym);
-        info.type = Rtype;
-        info.exists = true;
-        dm->registerData(info.data);//, __LINE__, __FILE__);
-
-        return info;
+        return parent->getTmpId(type, isAnInt);
     }
 
-    Info & Block::addShare(const symbol::Symbol & Lsym, const symbol::Symbol & Rsym, const TIType & Rtype, ast::Exp * exp)
+    return -1;
+}
+
+void Block::releaseTmp(const int id)
+{
+    if (parent)
     {
-       addLocal(Lsym, Rtype, /* isIntIterator */ false);
-        Info & Linfo = putAndClear(Lsym, exp);
-        Info & Rinfo = putSymsInScope(Rsym);
-        Linfo.cleared = false;
-        Linfo.type = Rtype;
-        Linfo.data = Rinfo.data;
-        Linfo.isint = Rinfo.isint;
-        Linfo.data->add(Lsym);
-        Linfo.exists = true;
-
-        return Linfo;
+        parent->releaseTmp(id);
     }
+}
 
-    Info & Block::addClear(const symbol::Symbol & sym, ast::Exp * exp)
+Info & Block::addDefine(const symbol::Symbol & sym, const TIType & Rtype, const bool isIntIterator, ast::Exp * exp)
+{
+    /* DEFINE:
+       - if associated data is shared then we need to clone it
+    */
+    addLocal(sym, Rtype, isIntIterator);
+    Info & info = putAndClear(sym, exp);
+    info.cleared = false;
+    info.data = new Data(true, sym);
+    info.type = Rtype;
+    info.exists = true;
+    dm->registerData(info.data);//, __LINE__, __FILE__);
+
+    return info;
+}
+
+Info & Block::addShare(const symbol::Symbol & Lsym, const symbol::Symbol & Rsym, const TIType & Rtype, ast::Exp * exp)
+{
+    addLocal(Lsym, Rtype, /* isIntIterator */ false);
+    Info & Linfo = putAndClear(Lsym, exp);
+    Info & Rinfo = putSymsInScope(Rsym);
+    Linfo.cleared = false;
+    Linfo.type = Rtype;
+    Linfo.data = Rinfo.data;
+    Linfo.isint = Rinfo.isint;
+    Linfo.data->add(Lsym);
+    Linfo.exists = true;
+
+    return Linfo;
+}
+
+Info & Block::addClear(const symbol::Symbol & sym, ast::Exp * exp)
+{
+    return putAndClear(sym, exp);
+}
+
+Info & Block::addMacroDef(ast::FunctionDec * dec)
+{
+    TIType ty(getGVN(), TIType::MACRO);
+    Info & i = addDefine(dec->getSymbol(), ty, false, dec);
+    i.exp = dec;
+
+    return i;
+}
+
+std::vector<TIType> Block::addCall(AnalysisVisitor & visitor, const unsigned int lhs, const symbol::Symbol & sym, std::vector<TIType> & in, ast::CallExp * callexp)
+{
+    tools::SymbolMap<Info>::iterator it;
+    Block * block = getDefBlock(sym, it, false);
+    types::InternalType * pIT = nullptr;
+    std::vector<TIType> out(lhs, TIType(visitor.getGVN()));
+    TIType type;
+
+    if (block)
     {
-        return putAndClear(sym, exp);
+        type = it->second.type;
     }
-
-    Info & Block::addMacroDef(ast::FunctionDec * dec)
+    else
     {
-        TIType ty(getGVN(), TIType::MACRO);
-       Info & i = addDefine(dec->getSymbol(), ty, false, dec);
-       i.exp = dec;
-
-       return i;
+        type = DataManager::getSymInScilabContext(getGVN(), sym, pIT);
     }
 
-    std::vector<TIType> Block::addCall(AnalysisVisitor & visitor, const unsigned int lhs, const symbol::Symbol & sym, std::vector<TIType> & in, ast::CallExp * callexp)
+    switch (type.type)
     {
-        std::map<symbol::Symbol, Info>::iterator it;
-        Block * block = getDefBlock(sym, it, false);
-        types::InternalType * pIT = nullptr;
-        std::vector<TIType> out(lhs, TIType(visitor.getGVN()));
-        TIType type;
-       
-        if (block)
-        {
-            type = it->second.type;
-        }
-        else
-        {
-            type = DataManager::getSymInScilabContext(getGVN(), sym, pIT);
-        }
-
-        switch (type.type)
-        {
         case TIType::FUNCTION:
         {
             if (lhs > 0)
             {
-               TIType ty = Checkers::check(getGVN(), sym.getName(), in);
-               if (ty.type != TIType::UNKNOWN && ty.hasInvalidDims())
-               {
-                   out[0] = ty.asUnknownMatrix();
-               }
-               else
-               {
-                   out[0] = ty;
-               }
+                TIType ty = Checkers::check(getGVN(), sym.getName(), in);
+                if (ty.type != TIType::UNKNOWN && ty.hasInvalidDims())
+                {
+                    out[0] = ty.asUnknownMatrix();
+                }
+                else
+                {
+                    out[0] = ty;
+                }
             }
             break;
         }
@@ -320,79 +339,79 @@ namespace analysis
         }
         case TIType::MACROFILE:
         {
-           DataManager::getSymInScilabContext(getGVN(), sym, pIT);
-           visitor.getPMC().getOutTypes(visitor, dm->getMacroDef(static_cast<types::MacroFile *>(pIT)->getMacro()), in, out);
+            DataManager::getSymInScilabContext(getGVN(), sym, pIT);
+            visitor.getPMC().getOutTypes(visitor, dm->getMacroDef(static_cast<types::MacroFile *>(pIT)->getMacro()), in, out);
             break;
         }
         default:
         {
         }
-       }
-
-        return out;
     }
 
-    Info & Block::putAndClear(const symbol::Symbol & sym, ast::Exp * exp)
+    return out;
+}
+
+Info & Block::putAndClear(const symbol::Symbol & sym, ast::Exp * exp)
+{
+    tools::SymbolMap<Info>::iterator it;
+    Block * block = getDefBlock(sym, it, false);
+    if (block)
     {
-        std::map<symbol::Symbol, Info>::iterator it;
-        Block * block = getDefBlock(sym, it, false);
-        if (block)
+        Info & info = it->second;
+        if (block == this)
         {
-            Info & info = it->second;
-            if (block == this)
+            if (info.data->hasOneOwner())
             {
-                if (info.data->hasOneOwner())
-                {
-                    info.cleared = true;
-                    info.local = Info::Local::INFO_TRUE;
-                    return info;
-                }
-                else
-                {
-                    info.data->rem(sym);
-                    info.data = nullptr;
-                    info.cleared = true;
-                    info.local = Info::Local::INFO_TRUE;
-                    return info;
-                }
+                info.cleared = true;
+                info.local = Info::Local::INFO_TRUE;
+                return info;
             }
             else
             {
-                if (info.data->hasOneOwner())
-                {
-                    Data * old = info.data;
-                    info.data = nullptr;
-                    Info & i = addSym(sym, info);
-                    info.data = old;
-                    i.cleared = true;
-                    i.local = Info::Local::INFO_TRUE;
-                    return i;
-                }
-                else
-                {
-                    Info & i = putSymsInScope(sym, block, info);
-                    i.data->rem(sym);
-                    i.data = nullptr;
-                    i.cleared = true;
-                    i.local = Info::Local::INFO_TRUE;
-                    return i;
-                }
+                info.data->rem(sym);
+                info.data = nullptr;
+                info.cleared = true;
+                info.local = Info::Local::INFO_TRUE;
+                return info;
             }
         }
         else
         {
-            Info & i = addSym(sym, nullptr);
-            i.local = Info::Local::INFO_TRUE;
-
-            return i;
+            if (info.data->hasOneOwner())
+            {
+                Data * old = info.data;
+                info.data = nullptr;
+                Info & i = addSym(sym, info);
+                info.data = old;
+                i.cleared = true;
+                i.local = Info::Local::INFO_TRUE;
+                return i;
+            }
+            else
+            {
+                Info & i = putSymsInScope(sym, block, info);
+                i.data->rem(sym);
+                i.data = nullptr;
+                i.cleared = true;
+                i.local = Info::Local::INFO_TRUE;
+                return i;
+            }
         }
     }
+    else
+    {
+        Info & i = addSym(sym, nullptr);
+        i.local = Info::Local::INFO_TRUE;
+
+        return i;
+    }
+}
 
-    Block * Block::addBlock(const unsigned int id, BlockKind kind, ast::Exp * exp)
+Block * Block::addBlock(const unsigned int id, BlockKind kind, ast::Exp * exp)
+{
+    Block * b;
+    switch (kind)
     {
-        Block * b;
-        switch (kind)
-        {
         case NORMAL:
             b = new Block(id, this, exp);
             break;
@@ -405,108 +424,108 @@ namespace analysis
         case MACRO:
             b = new FunctionBlock(id, this, exp);
             break;
-        }
-        blocks.push_back(b);
-
-        return b;
     }
+    blocks.push_back(b);
+
+    return b;
+}
+
+void Block::finalize()
+{
+    pullup(symMap);
+}
 
-    void Block::finalize()
+bool Block::requiresAnotherTrip()
+{
+    return false;
+}
+
+void Block::merge(tools::SymbolMap<Info> & M, tools::SymbolMap<Info> & N)
+{
+    // TODO: when we merge double and double* we should mark the sym to convert the double into a double*
+    // and in the LLVM side, make a phi node to set the correct value !
+    for (auto & p : M)
     {
-        pullup(symMap);
+        tools::SymbolMap<Info>::iterator i = N.find(p.first);
+        if (i != N.end())
+        {
+            // sym is common to the two maps
+            p.second.merge(i->second);
+            N.erase(i);
+        }
+        else
+        {
+            // sym is in M and not in N
+            Info & i = getInfo(p.first);
+            p.second.merge(i);
+        }
     }
 
-    bool Block::requiresAnotherTrip()
+    // We erased common syms in N, so the remainder is the syms which are in N and not in M
+    for (auto & p : N)
     {
-        return false;
+        Block::addSym(M, p.first, p.second).merge(getInfo(p.first));
     }
+}
 
-    void Block::merge(std::map<symbol::Symbol, Info> & M, std::map<symbol::Symbol, Info> & N)
+void Block::pullup(tools::SymbolMap<Info> & M)
+{
+    if (parent)
     {
-        // TODO: when we merge double and double* we should mark the sym to convert the double into a double*
-        // and in the LLVM side, make a phi node to set the correct value !
+        tools::SymbolMap<Info> & map = parent->symMap;
+        tools::SymbolMap<Info>::iterator end = map.end();
         for (auto & p : M)
         {
-            std::map<symbol::Symbol, Info>::iterator i = N.find(p.first);
-            if (i != N.end())
+            tools::SymbolMap<Info>::iterator i = map.find(p.first);
+            if (i != end)
             {
-                // sym is common to the two maps
-                p.second.merge(i->second);
-                N.erase(i);
+                i->second = p.second;
             }
             else
             {
-                // sym is in M and not in N
-                Info & i = getInfo(p.first);
-                p.second.merge(i);
+                Block::addSym(map, p.first, p.second);
             }
         }
-
-        // We erased common syms in N, so the remainder is the syms which are in N and not in M
-        for (auto & p : N)
-        {
-            Block::addSym(M, p.first, p.second).merge(getInfo(p.first));
-        }
     }
+}
+
+Info & Block::addSym(tools::SymbolMap<Info> & M, const symbol::Symbol & sym, Info & info)
+{
+    Data * old = info.data;
+    info.data = nullptr;
+    Info & i = M.emplace(sym, info).first->second;
+    i.data = old;
+    info.data = old;
+
+    return i;
+}
 
-    void Block::pullup(std::map<symbol::Symbol, Info> & M)
+std::wostream & operator<<(std::wostream & out, const Block & block)
+{
+    const unsigned int n = block.blocks.size();
+    out << L"Table " << block.id;
+    if (block.exp)
     {
-        if (parent)
-        {
-            std::map<symbol::Symbol, Info> & map = parent->symMap;
-            std::map<symbol::Symbol, Info>::iterator end = map.end();
-            for (auto & p : M)
-            {
-                std::map<symbol::Symbol, Info>::iterator i = map.find(p.first);
-                if (i != end)
-                {
-                    i->second = p.second;
-                }
-                else
-                {
-                    Block::addSym(map, p.first, p.second);
-                }
-            }
-        }
+        out << L" at " << block.exp->getLocation();
     }
+    out << L" (" << n << ((n >= 2) ? L" children):" : L" child):") << std::endl;
 
-    Info & Block::addSym(std::map<symbol::Symbol, Info> & M, const symbol::Symbol & sym, Info & info)
+    for (const auto & p : block.symMap)
     {
-       Data * old = info.data;
-       info.data = nullptr;
-       Info & i = M.emplace(sym, info).first->second;
-       i.data = old;
-       info.data = old;
-       
-       return i;
+        out << L" -" << p.first << L"  " << p.second << std::endl;
     }
-    
-    std::wostream & operator<<(std::wostream & out, const Block & block)
+    //#ifdef DEBUG_DATAMANAGER
+    //for (const auto b : block.blocks)
+    //{
+
+    //}
+    std::for_each(block.blocks.begin(), block.blocks.end(), [&](Block * b)
     {
-        const unsigned int n = block.blocks.size();
-        out << L"Table " << block.id;
-       if (block.exp)
-       {
-           out << L" at " << block.exp->getLocation();
-       }
-       out << L" (" << n << ((n >= 2) ? L" children):" : L" child):") << std::endl;
-
-        for (const auto & p : block.symMap)
-        {
-            out << L" -" << p.first << L"  " << p.second << std::endl;
-        }
-        //#ifdef DEBUG_DATAMANAGER
-        //for (const auto b : block.blocks)
-        //{
-
-        //}
-        std::for_each(block.blocks.begin(), block.blocks.end(), [&](Block * b)
-                      {
-                          out << *b << std::endl;
-                      });
-        //#endif
-
-        return out;
-    }
+        out << *b << std::endl;
+    });
+    //#endif
+
+    return out;
+}
 
 } // namespace analysis
index c5792c2..aba94ce 100644 (file)
@@ -16,7 +16,9 @@
 
 namespace analysis
 {
-    bool CeilAnalyzer::analyze(AnalysisVisitor & visitor, const unsigned int lhs, ast::CallExp & e)
+bool CeilAnalyzer::analyze(AnalysisVisitor & visitor, const unsigned int lhs, ast::CallExp & e)
+{
+    if (lhs <= 1)
     {
         const ast::exps_t args = e.getArgs();
         if (args.size() == 1)
@@ -25,20 +27,36 @@ namespace analysis
             (*first)->accept(visitor);
             Result & R = visitor.getResult();
             const TIType & Rtype = R.getType();
+            const symbol::Symbol & sym = static_cast<ast::SimpleVar &>(e.getName()).getSymbol();
+            const std::wstring & name = sym.getName();
+            std::vector<TIType> vargs({ Rtype });
+            std::vector<TIType> out = visitor.getDM().call(visitor, lhs, sym, vargs, &e);
             if (Rtype.isintegral())
             {
-               const ast::SimpleVar & var = static_cast<ast::SimpleVar &>(e.getName());
-               const symbol::Symbol & sym = var.getSymbol();
-               const std::wstring & name = sym.getName();
+                const ast::SimpleVar & var = static_cast<ast::SimpleVar &>(e.getName());
 
-               e.getDecorator().res = Result(Rtype);
-                e.getDecorator().setCall(name);
+                e.getDecorator().res = Result(Rtype, R.getTempId());
+                e.getDecorator().setCall(name, vargs);
                 visitor.setResult(e.getDecorator().res);
 
                 return true;
             }
-        }
 
-        return false;  
+            if (out[0].type != TIType::UNKNOWN)
+            {
+                e.getDecorator().res = Result(Rtype, R.getTempId());
+                e.getDecorator().setCall(name, vargs);
+                visitor.setResult(e.getDecorator().res);
+
+                return true;
+            }
+            else
+            {
+                visitor.getDM().releaseTmp(R.getTempId());
+            }
+        }
     }
+
+    return false;
+}
 }
index e5410dd..89c3362 100644 (file)
 
 namespace analysis
 {
-        TIType (*Checkers::ARGS0[6])(GVN &);
-        TIType (*Checkers::ARGS1[53])(GVN &, const TIType &);
-        TIType (*Checkers::ARGS2[10])(GVN &, const TIType &, const TIType &);
-        TIType (*Checkers::ARGS3[1])(GVN &, const TIType &, const TIType &, const TIType &);
+TIType (*Checkers::ARGS0[6])(GVN &);
+TIType (*Checkers::ARGS1[54])(GVN &, const TIType &);
+TIType (*Checkers::ARGS2[10])(GVN &, const TIType &, const TIType &);
+TIType (*Checkers::ARGS3[1])(GVN &, const TIType &, const TIType &, const TIType &);
 
-        Checkers::CheckersMap Checkers::map = Checkers::initMap();
+Checkers::CheckersMap Checkers::map = Checkers::initMap();
 
-        TIType Checkers::check(GVN & gvn, const std::wstring & name, const std::vector<TIType> & args)
+TIType Checkers::check(GVN & gvn, const std::wstring & name, const std::vector<TIType> & args)
+{
+    const unsigned short size = args.size();
+    CheckersMap::const_iterator i = map.find(__NName(size, name));
+    if (i != map.end())
+    {
+        // TODO : remove array of function pointers and replace by a switch statement
+        switch (size)
         {
-            const unsigned short size = args.size();
-            CheckersMap::const_iterator i = map.find(__NName(size, name));
-            if (i != map.end())
-            {
-                // TODO : remove array of function pointers and replace by a switch statement
-                switch (size)
-                {
-                case 0:
-                     return ARGS0[i->second.pos](gvn);
-                case 1:
-                     return ARGS1[i->second.pos](gvn, args[0]);
-                case 2:
-                     return ARGS2[i->second.pos](gvn, args[0], args[1]);
-                case 3:
-                     return ARGS3[i->second.pos](gvn, args[0], args[1], args[2]);
-                }
-            }
-            
-            return TIType(gvn);
+            case 0:
+                return ARGS0[i->second.pos](gvn);
+            case 1:
+                return ARGS1[i->second.pos](gvn, args[0]);
+            case 2:
+                return ARGS2[i->second.pos](gvn, args[0], args[1]);
+            case 3:
+                return ARGS3[i->second.pos](gvn, args[0], args[1], args[2]);
         }
+    }
 
-        bool Checkers::isElementWise(const std::wstring & name, unsigned short nargs)
-        {
-            CheckersMap::const_iterator i = map.find(__NName(nargs, name));
-            if (i != map.end())
-            {
-                return i->second.elementwise;
-            }
-            return false;
-        }
+    return TIType(gvn);
+}
 
-        bool Checkers::isJitted(const std::wstring & name, unsigned short nargs)
-        {
-            CheckersMap::const_iterator i = map.find(__NName(nargs, name));
-            if (i != map.end())
-            {
-                return i->second.jitted;
-            }
-            return false;
-        }
+bool Checkers::isElementWise(const std::wstring & name, unsigned short nargs)
+{
+    CheckersMap::const_iterator i = map.find(__NName(nargs, name));
+    if (i != map.end())
+    {
+        return i->second.elementwise;
+    }
+    return false;
+}
 
-        bool Checkers::isConst(const std::wstring & name, unsigned short nargs)
-        {
-            CheckersMap::const_iterator i = map.find(__NName(nargs, name));
-            if (i != map.end())
-            {
-                return !i->second.notconst;
-            }
-            return false;
-        }
+bool Checkers::isJitted(const std::wstring & name, unsigned short nargs)
+{
+    CheckersMap::const_iterator i = map.find(__NName(nargs, name));
+    if (i != map.end())
+    {
+        return i->second.jitted;
+    }
+    return false;
+}
 
-        Checkers::CheckersMap Checkers::initMap()
-        {
-            CheckersMap map;
-            map.emplace(__NName(0, L"rand"), __Infos(0, false, true, false));
-            map.emplace(__NName(0, L"zeros"), __Infos(1, false, false, false));
-            map.emplace(__NName(0, L"ls"), __Infos(2, false, true, false));
-            map.emplace(__NName(0, L"toc"), __Infos(3, false, true, false));
-            map.emplace(__NName(0, L"argn"), __Infos(4, false, false, false));
-            map.emplace(__NName(0, L"ones"), __Infos(5, false, false, false));
-            map.emplace(__NName(1, L"rand"), __Infos(0, false, true, false));
-            map.emplace(__NName(1, L"isreal"), __Infos(1, false, false, false));
-            map.emplace(__NName(1, L"abs"), __Infos(2, true, false, true));
-            map.emplace(__NName(1, L"cosh"), __Infos(3, true, false, true));
-            map.emplace(__NName(1, L"typeof"), __Infos(4, false, false, false));
-            map.emplace(__NName(1, L"int16"), __Infos(5, true, false, true));
-            map.emplace(__NName(1, L"gettext"), __Infos(6, false, true, false));
-            map.emplace(__NName(1, L"tan"), __Infos(7, true, false, true));
-            map.emplace(__NName(1, L"cumsum"), __Infos(8, true, false, true));
-            map.emplace(__NName(1, L"size"), __Infos(9, false, false, false));
-            map.emplace(__NName(1, L"asin"), __Infos(10, true, false, false));
-            map.emplace(__NName(1, L"or"), __Infos(11, false, false, false));
-            map.emplace(__NName(1, L"log"), __Infos(12, true, false, false));
-            map.emplace(__NName(1, L"floor"), __Infos(13, true, false, true));
-            map.emplace(__NName(1, L"int"), __Infos(14, true, false, true));
-            map.emplace(__NName(1, L"fix"), __Infos(15, true, false, true));
-            map.emplace(__NName(1, L"sqrt"), __Infos(16, true, false, true));
-            map.emplace(__NName(1, L"uint16"), __Infos(17, true, false, true));
-            map.emplace(__NName(1, L"zeros"), __Infos(18, false, false, false));
-            map.emplace(__NName(1, L"ls"), __Infos(19, false, true, false));
-            map.emplace(__NName(1, L"max"), __Infos(20, false, false, true));
-            map.emplace(__NName(1, L"uint32"), __Infos(21, true, false, true));
-            map.emplace(__NName(1, L"int64"), __Infos(22, true, false, true));
-            map.emplace(__NName(1, L"prod"), __Infos(23, false, false, true));
-            map.emplace(__NName(1, L"type"), __Infos(24, false, false, false));
-            map.emplace(__NName(1, L"sin"), __Infos(25, true, false, true));
-            map.emplace(__NName(1, L"round"), __Infos(26, true, false, true));
-            map.emplace(__NName(1, L"int32"), __Infos(27, true, false, true));
-            map.emplace(__NName(1, L"inttype"), __Infos(28, false, false, false));
-            map.emplace(__NName(1, L"exp"), __Infos(29, true, false, true));
-            map.emplace(__NName(1, L"atan"), __Infos(30, true, false, false));
-            map.emplace(__NName(1, L"imag"), __Infos(31, false, false, false));
-            map.emplace(__NName(1, L"uint8"), __Infos(32, true, false, true));
-            map.emplace(__NName(1, L"ceil"), __Infos(33, true, false, true));
-            map.emplace(__NName(1, L"uint64"), __Infos(34, true, false, true));
-            map.emplace(__NName(1, L"sinm"), __Infos(35, false, false, false));
-            map.emplace(__NName(1, L"isinf"), __Infos(36, true, false, true));
-            map.emplace(__NName(1, L"sinh"), __Infos(37, true, false, true));
-            map.emplace(__NName(1, L"isscalar"), __Infos(38, false, false, false));
-            map.emplace(__NName(1, L"int8"), __Infos(39, true, false, true));
-            map.emplace(__NName(1, L"cos"), __Infos(40, true, false, true));
-            map.emplace(__NName(1, L"and"), __Infos(41, false, false, false));
-            map.emplace(__NName(1, L"tanh"), __Infos(42, true, false, true));
-            map.emplace(__NName(1, L"isnan"), __Infos(43, true, false, true));
-            map.emplace(__NName(1, L"imult"), __Infos(44, false, false, false));
-            map.emplace(__NName(1, L"argn"), __Infos(45, false, false, false));
-            map.emplace(__NName(1, L"cumprod"), __Infos(46, true, false, true));
-            map.emplace(__NName(1, L"erf"), __Infos(47, true, false, true));
-            map.emplace(__NName(1, L"ones"), __Infos(48, false, false, false));
-            map.emplace(__NName(1, L"erfc"), __Infos(49, true, false, true));
-            map.emplace(__NName(1, L"min"), __Infos(50, false, false, true));
-            map.emplace(__NName(1, L"sum"), __Infos(51, false, false, true));
-            map.emplace(__NName(1, L"acos"), __Infos(52, true, false, false));
-            map.emplace(__NName(2, L"rand"), __Infos(0, false, true, false));
-            map.emplace(__NName(2, L"isreal"), __Infos(1, false, false, false));
-            map.emplace(__NName(2, L"iconvert"), __Infos(2, false, false, false));
-            map.emplace(__NName(2, L"gettext"), __Infos(3, false, true, false));
-            map.emplace(__NName(2, L"size"), __Infos(4, false, false, false));
-            map.emplace(__NName(2, L"or"), __Infos(5, false, false, false));
-            map.emplace(__NName(2, L"zeros"), __Infos(6, false, false, false));
-            map.emplace(__NName(2, L"matrix"), __Infos(7, false, false, false));
-            map.emplace(__NName(2, L"and"), __Infos(8, false, false, false));
-            map.emplace(__NName(2, L"ones"), __Infos(9, false, false, false));
-            map.emplace(__NName(3, L"matrix"), __Infos(0, false, false, false));           
-            ARGS0[0] = &check_rand;
-            ARGS0[1] = &check_zeros;
-            ARGS0[2] = &check_ls;
-            ARGS0[3] = &check_toc;
-            ARGS0[4] = &check_argn;
-            ARGS0[5] = &check_ones;
-            ARGS1[0] = &check_rand;
-            ARGS1[1] = &check_isreal;
-            ARGS1[2] = &check_abs;
-            ARGS1[3] = &check_cosh;
-            ARGS1[4] = &check_typeof;
-            ARGS1[5] = &check_int16;
-            ARGS1[6] = &check_gettext;
-            ARGS1[7] = &check_tan;
-            ARGS1[8] = &check_cumsum;
-            ARGS1[9] = &check_size;
-            ARGS1[10] = &check_asin;
-            ARGS1[11] = &check_or;
-            ARGS1[12] = &check_log;
-            ARGS1[13] = &check_floor;
-            ARGS1[14] = &check_int;
-            ARGS1[15] = &check_fix;
-            ARGS1[16] = &check_sqrt;
-            ARGS1[17] = &check_uint16;
-            ARGS1[18] = &check_zeros;
-            ARGS1[19] = &check_ls;
-            ARGS1[20] = &check_max;
-            ARGS1[21] = &check_uint32;
-            ARGS1[22] = &check_int64;
-            ARGS1[23] = &check_prod;
-            ARGS1[24] = &check_type;
-            ARGS1[25] = &check_sin;
-            ARGS1[26] = &check_round;
-            ARGS1[27] = &check_int32;
-            ARGS1[28] = &check_inttype;
-            ARGS1[29] = &check_exp;
-            ARGS1[30] = &check_atan;
-            ARGS1[31] = &check_imag;
-            ARGS1[32] = &check_uint8;
-            ARGS1[33] = &check_ceil;
-            ARGS1[34] = &check_uint64;
-            ARGS1[35] = &check_sinm;
-            ARGS1[36] = &check_isinf;
-            ARGS1[37] = &check_sinh;
-            ARGS1[38] = &check_isscalar;
-            ARGS1[39] = &check_int8;
-            ARGS1[40] = &check_cos;
-            ARGS1[41] = &check_and;
-            ARGS1[42] = &check_tanh;
-            ARGS1[43] = &check_isnan;
-            ARGS1[44] = &check_imult;
-            ARGS1[45] = &check_argn;
-            ARGS1[46] = &check_cumprod;
-            ARGS1[47] = &check_erf;
-            ARGS1[48] = &check_ones;
-            ARGS1[49] = &check_erfc;
-            ARGS1[50] = &check_min;
-            ARGS1[51] = &check_sum;
-            ARGS1[52] = &check_acos;
-            ARGS2[0] = &check_rand;
-            ARGS2[1] = &check_isreal;
-            ARGS2[2] = &check_iconvert;
-            ARGS2[3] = &check_gettext;
-            ARGS2[4] = &check_size;
-            ARGS2[5] = &check_or;
-            ARGS2[6] = &check_zeros;
-            ARGS2[7] = &check_matrix;
-            ARGS2[8] = &check_and;
-            ARGS2[9] = &check_ones;
-            ARGS3[0] = &check_matrix;
+bool Checkers::isConst(const std::wstring & name, unsigned short nargs)
+{
+    CheckersMap::const_iterator i = map.find(__NName(nargs, name));
+    if (i != map.end())
+    {
+        return !i->second.notconst;
+    }
+    return false;
+}
 
-            return map;
-        }
+Checkers::CheckersMap Checkers::initMap()
+{
+    CheckersMap map;
+    map.emplace(__NName(0, L"rand"), __Infos(0, false, true, false));
+    map.emplace(__NName(0, L"zeros"), __Infos(1, false, false, false));
+    map.emplace(__NName(0, L"ls"), __Infos(2, false, true, false));
+    map.emplace(__NName(0, L"toc"), __Infos(3, false, true, false));
+    map.emplace(__NName(0, L"argn"), __Infos(4, false, false, false));
+    map.emplace(__NName(0, L"ones"), __Infos(5, false, false, false));
+    map.emplace(__NName(1, L"rand"), __Infos(0, false, true, false));
+    map.emplace(__NName(1, L"isreal"), __Infos(1, false, false, false));
+    map.emplace(__NName(1, L"abs"), __Infos(2, true, false, true));
+    map.emplace(__NName(1, L"cosh"), __Infos(3, true, false, true));
+    map.emplace(__NName(1, L"typeof"), __Infos(4, false, false, false));
+    map.emplace(__NName(1, L"int16"), __Infos(5, true, false, true));
+    map.emplace(__NName(1, L"gettext"), __Infos(6, false, true, false));
+    map.emplace(__NName(1, L"tan"), __Infos(7, true, false, true));
+    map.emplace(__NName(1, L"cumsum"), __Infos(8, true, false, true));
+    map.emplace(__NName(1, L"size"), __Infos(9, false, false, false));
+    map.emplace(__NName(1, L"asin"), __Infos(10, true, false, false));
+    map.emplace(__NName(1, L"or"), __Infos(11, false, false, false));
+    map.emplace(__NName(1, L"log"), __Infos(12, true, false, false));
+    map.emplace(__NName(1, L"floor"), __Infos(13, true, false, true));
+    map.emplace(__NName(1, L"int"), __Infos(14, true, false, true));
+    map.emplace(__NName(1, L"fix"), __Infos(15, true, false, true));
+    map.emplace(__NName(1, L"sqrt"), __Infos(16, true, false, true));
+    map.emplace(__NName(1, L"uint16"), __Infos(17, true, false, true));
+    map.emplace(__NName(1, L"zeros"), __Infos(18, false, false, false));
+    map.emplace(__NName(1, L"ls"), __Infos(19, false, true, false));
+    map.emplace(__NName(1, L"max"), __Infos(20, false, false, true));
+    map.emplace(__NName(1, L"uint32"), __Infos(21, true, false, true));
+    map.emplace(__NName(1, L"int64"), __Infos(22, true, false, true));
+    map.emplace(__NName(1, L"prod"), __Infos(23, false, false, true));
+    map.emplace(__NName(1, L"type"), __Infos(24, false, false, false));
+    map.emplace(__NName(1, L"sin"), __Infos(25, true, false, true));
+    map.emplace(__NName(1, L"round"), __Infos(26, true, false, true));
+    map.emplace(__NName(1, L"int32"), __Infos(27, true, false, true));
+    map.emplace(__NName(1, L"inttype"), __Infos(28, false, false, false));
+    map.emplace(__NName(1, L"exp"), __Infos(29, true, false, true));
+    map.emplace(__NName(1, L"atan"), __Infos(30, true, false, true));
+    map.emplace(__NName(1, L"imag"), __Infos(31, false, false, false));
+    map.emplace(__NName(1, L"uint8"), __Infos(32, true, false, true));
+    map.emplace(__NName(1, L"ceil"), __Infos(33, true, false, true));
+    map.emplace(__NName(1, L"uint64"), __Infos(34, true, false, true));
+    map.emplace(__NName(1, L"sinm"), __Infos(35, false, false, false));
+    map.emplace(__NName(1, L"isinf"), __Infos(36, true, false, true));
+    map.emplace(__NName(1, L"sinh"), __Infos(37, true, false, true));
+    map.emplace(__NName(1, L"isscalar"), __Infos(38, false, false, false));
+    map.emplace(__NName(1, L"sign"), __Infos(39, true, false, true));
+    map.emplace(__NName(1, L"int8"), __Infos(40, true, false, true));
+    map.emplace(__NName(1, L"cos"), __Infos(41, true, false, true));
+    map.emplace(__NName(1, L"and"), __Infos(42, false, false, false));
+    map.emplace(__NName(1, L"tanh"), __Infos(43, true, false, true));
+    map.emplace(__NName(1, L"isnan"), __Infos(44, true, false, true));
+    map.emplace(__NName(1, L"imult"), __Infos(45, false, false, false));
+    map.emplace(__NName(1, L"argn"), __Infos(46, false, false, false));
+    map.emplace(__NName(1, L"cumprod"), __Infos(47, true, false, true));
+    map.emplace(__NName(1, L"erf"), __Infos(48, true, false, true));
+    map.emplace(__NName(1, L"ones"), __Infos(49, false, false, false));
+    map.emplace(__NName(1, L"erfc"), __Infos(50, true, false, true));
+    map.emplace(__NName(1, L"min"), __Infos(51, false, false, true));
+    map.emplace(__NName(1, L"sum"), __Infos(52, false, false, true));
+    map.emplace(__NName(1, L"acos"), __Infos(53, true, false, false));
+    map.emplace(__NName(2, L"rand"), __Infos(0, false, true, false));
+    map.emplace(__NName(2, L"isreal"), __Infos(1, false, false, false));
+    map.emplace(__NName(2, L"iconvert"), __Infos(2, false, false, false));
+    map.emplace(__NName(2, L"gettext"), __Infos(3, false, true, false));
+    map.emplace(__NName(2, L"size"), __Infos(4, false, false, false));
+    map.emplace(__NName(2, L"or"), __Infos(5, false, false, false));
+    map.emplace(__NName(2, L"zeros"), __Infos(6, false, false, false));
+    map.emplace(__NName(2, L"matrix"), __Infos(7, false, false, false));
+    map.emplace(__NName(2, L"and"), __Infos(8, false, false, false));
+    map.emplace(__NName(2, L"ones"), __Infos(9, false, false, false));
+    map.emplace(__NName(3, L"matrix"), __Infos(0, false, false, false));
+    ARGS0[0] = &check_rand;
+    ARGS0[1] = &check_zeros;
+    ARGS0[2] = &check_ls;
+    ARGS0[3] = &check_toc;
+    ARGS0[4] = &check_argn;
+    ARGS0[5] = &check_ones;
+    ARGS1[0] = &check_rand;
+    ARGS1[1] = &check_isreal;
+    ARGS1[2] = &check_abs;
+    ARGS1[3] = &check_cosh;
+    ARGS1[4] = &check_typeof;
+    ARGS1[5] = &check_int16;
+    ARGS1[6] = &check_gettext;
+    ARGS1[7] = &check_tan;
+    ARGS1[8] = &check_cumsum;
+    ARGS1[9] = &check_size;
+    ARGS1[10] = &check_asin;
+    ARGS1[11] = &check_or;
+    ARGS1[12] = &check_log;
+    ARGS1[13] = &check_floor;
+    ARGS1[14] = &check_int;
+    ARGS1[15] = &check_fix;
+    ARGS1[16] = &check_sqrt;
+    ARGS1[17] = &check_uint16;
+    ARGS1[18] = &check_zeros;
+    ARGS1[19] = &check_ls;
+    ARGS1[20] = &check_max;
+    ARGS1[21] = &check_uint32;
+    ARGS1[22] = &check_int64;
+    ARGS1[23] = &check_prod;
+    ARGS1[24] = &check_type;
+    ARGS1[25] = &check_sin;
+    ARGS1[26] = &check_round;
+    ARGS1[27] = &check_int32;
+    ARGS1[28] = &check_inttype;
+    ARGS1[29] = &check_exp;
+    ARGS1[30] = &check_atan;
+    ARGS1[31] = &check_imag;
+    ARGS1[32] = &check_uint8;
+    ARGS1[33] = &check_ceil;
+    ARGS1[34] = &check_uint64;
+    ARGS1[35] = &check_sinm;
+    ARGS1[36] = &check_isinf;
+    ARGS1[37] = &check_sinh;
+    ARGS1[38] = &check_isscalar;
+    ARGS1[39] = &check_sign;
+    ARGS1[40] = &check_int8;
+    ARGS1[41] = &check_cos;
+    ARGS1[42] = &check_and;
+    ARGS1[43] = &check_tanh;
+    ARGS1[44] = &check_isnan;
+    ARGS1[45] = &check_imult;
+    ARGS1[46] = &check_argn;
+    ARGS1[47] = &check_cumprod;
+    ARGS1[48] = &check_erf;
+    ARGS1[49] = &check_ones;
+    ARGS1[50] = &check_erfc;
+    ARGS1[51] = &check_min;
+    ARGS1[52] = &check_sum;
+    ARGS1[53] = &check_acos;
+    ARGS2[0] = &check_rand;
+    ARGS2[1] = &check_isreal;
+    ARGS2[2] = &check_iconvert;
+    ARGS2[3] = &check_gettext;
+    ARGS2[4] = &check_size;
+    ARGS2[5] = &check_or;
+    ARGS2[6] = &check_zeros;
+    ARGS2[7] = &check_matrix;
+    ARGS2[8] = &check_and;
+    ARGS2[9] = &check_ones;
+    ARGS3[0] = &check_matrix;
 
+    return map;
 }
+
+}
\ No newline at end of file
index 5dd9e68..7d8a9c9 100644 (file)
@@ -35,23 +35,23 @@ const MacroOut * CompleteMacroSignature::analyze(AnalysisVisitor & visitor, cons
 {
     if (signature.lhs <= macrodef->getLhs())
     {
-       visitor.getLogger().log(L"Visit macro ", macrodef->getName());
+        visitor.getLogger().log(L"Visit macro ", macrodef->getName());
         dm.addBlock(Block::MACRO, &macrodef->getBody());
         FunctionBlock & fblock = *static_cast<FunctionBlock *>(dm.getCurrent());
         fblock.setName(macrodef->getName());
         fblock.setLhsRhs(signature.lhs, rhs);
         fblock.setInOut(macrodef, rhs, in);
-       fblock.setGlobals(macrodef->getGlobals());
+        fblock.setGlobals(macrodef->getGlobals());
         if (!fblock.addIn(signature.tuple, values))
         {
-           dm.finalizeBlock();
+            dm.finalizeBlock();
             return nullptr;
         }
 
         fblock.getExp()->accept(visitor);
         dm.finalizeBlock();
-       visitor.emitFunctionBlock(fblock);
-       //std::wcerr << fblock << std::endl;
+        //std::wcerr << fblock << std::endl;
+        visitor.emitFunctionBlock(fblock);
         outMap.emplace_back(fblock.getConstraints(), fblock.getGlobalConstants(), fblock.getOuts());
 
         return &outMap.back().out;
index 0da5444..e8b4564 100644 (file)
 namespace analysis
 {
 
-    std::unordered_set<std::wstring> ConstantVisitor::constants = init();
+std::unordered_set<std::wstring> ConstantVisitor::constants = init();
 
-    void ConstantVisitor::visit(ast::SimpleVar & e)
+void ConstantVisitor::visit(ast::SimpleVar & e)
+{
+    bool isConstant = false;
+    if (evalSymbols)
     {
-        bool isConstant = false;
-        if (evalSymbols)
+        const symbol::Symbol & sym = e.getSymbol();
+        const std::wstring & name = sym.getName();
+        if (constants.find(name) != constants.end() && symbol::Context::getInstance()->isOriginalSymbol(sym))
         {
-            const symbol::Symbol & sym = e.getSymbol();
-            const std::wstring & name = sym.getName();
-            if (constants.find(name) != constants.end() && symbol::Context::getInstance()->isOriginalSymbol(sym))
+            if (types::InternalType * pIT = symbol::Context::getInstance()->get(sym))
             {
-                if (types::InternalType * pIT = symbol::Context::getInstance()->get(sym))
-                {
-                    e.replace(pIT->getExp(e.getLocation()));
-                    isConstant = true;
-                }
+                e.replace(pIT->getExp(e.getLocation()));
+                isConstant = true;
             }
-            else if (parent)
+        }
+        else if (parent)
+        {
+            if (FunctionBlock * fblock = parent->getDM().topFunction())
             {
-                Info & info = parent->getDM().read(sym, &e);
-                ConstantValue & constant = info.getConstant();
-                const ConstantValue::Kind kind = constant.getKind();
-                if (kind == ConstantValue::GVNVAL)
+                ast::Exp * loop = parent->getCurrentLoop();
+                if (!fblock->getLoopAnalyzer().isAssigned(loop, sym))
                 {
-                    double val;
-                    if (constant.getDblValue(val))
+                    // We propagate the constant only if we aren't in a loop which modifies the sym
+                    Info & info = parent->getDM().read(sym, &e);
+                    ConstantValue & constant = info.getConstant();
+                    const ConstantValue::Kind kind = constant.getKind();
+                    if (kind == ConstantValue::GVNVAL)
                     {
-                        e.replace(new ast::DoubleExp(e.getLocation(), val));
-                        isConstant = true;
+                        double val;
+                        if (constant.getDblValue(val))
+                        {
+                            e.replace(new ast::DoubleExp(e.getLocation(), val));
+                            isConstant = true;
+                        }
                     }
-                }
-                else if (kind == ConstantValue::ITVAL)
-                {
-                    types::InternalType * pIT = constant.getIT();
-                    if (ast::Exp * exp = pIT->getExp(e.getLocation()))
+                    else if (kind == ConstantValue::ITVAL)
                     {
-                        e.replace(exp);
-                        isConstant = true;
+                        types::InternalType * pIT = constant.getIT();
+                        if (ast::Exp * exp = pIT->getExp(e.getLocation()))
+                        {
+                            e.replace(exp);
+                            isConstant = true;
+                        }
                     }
                 }
             }
         }
-
-        setResult(isConstant);
     }
 
-    void ConstantVisitor::visit(ast::OpExp & e)
-    {
-        e.getLeft().accept(*this);
-        const bool constL = getResult();
-        e.getRight().accept(*this);
-        const bool constR = getResult();
+    setResult(isConstant);
+}
 
-        if (constL && constR)
-        {
-            setResult(execAndReplace(e));
-            return;
-        }
-        else if (constL || constR)
+void ConstantVisitor::visit(ast::OpExp & e)
+{
+    e.getLeft().accept(*this);
+    const bool constL = getResult();
+    e.getRight().accept(*this);
+    const bool constR = getResult();
+
+    if (constL && constR)
+    {
+        setResult(execAndReplace(e));
+        return;
+    }
+    else if (constL || constR)
+    {
+        const ast::Exp::ExpType ty = e.getParent()->getType();
+        if (ty == ast::Exp::IFEXP || ty == ast::Exp::WHILEEXP)
         {
-            const ast::Exp::ExpType ty = e.getParent()->getType();
-            if (ty == ast::Exp::IFEXP || ty == ast::Exp::WHILEEXP)
+            ast::OpExp::Oper oper = e.getOper();
+            if (oper == ast::OpExp::Oper::logicalShortCutAnd || oper == ast::OpExp::Oper::logicalAnd)
             {
-                ast::OpExp::Oper oper = e.getOper();
-                if (oper == ast::OpExp::Oper::logicalShortCutAnd || oper == ast::OpExp::Oper::logicalAnd)
+                if (constL)
                 {
-                    if (constL)
+                    e.getLeft().accept(exec);
+                    if (exec.getResult()->isTrue())
                     {
-                        e.getLeft().accept(exec);
-                        if (exec.getResult()->isTrue())
-                        {
-                            e.replace(e.getRight().clone());
-                        }
-                        else
-                        {
-                            types::InternalType * b = new types::Bool(0);
-                            e.replace(b->getExp(e.getLocation()));
-                            setResult(true);
-                            return;
-                        }
+                        e.replace(e.getRight().clone());
                     }
                     else
                     {
-                        e.getRight().accept(exec);
-                        if (exec.getResult()->isTrue())
-                        {
-                            e.replace(e.getLeft().clone());
-                        }
-                        else
-                        {
-                            types::InternalType * b = new types::Bool(0);
-                            e.replace(b->getExp(e.getLocation()));
-                            setResult(true);
-                            return;
-                        }
+                        types::InternalType * b = new types::Bool(0);
+                        e.replace(b->getExp(e.getLocation()));
+                        setResult(true);
+                        return;
                     }
                 }
-                else if (oper == ast::OpExp::Oper::logicalShortCutOr || oper == ast::OpExp::Oper::logicalOr)
+                else
                 {
-                    if (constL)
+                    e.getRight().accept(exec);
+                    if (exec.getResult()->isTrue())
                     {
-                        e.getLeft().accept(exec);
-                        if (exec.getResult()->isTrue())
-                        {
-                            types::InternalType * b = new types::Bool(1);
-                            e.replace(b->getExp(e.getLocation()));
-                            setResult(true);
-                            return;
-                        }
-                        else
-                        {
-                            e.replace(e.getRight().clone());
-                        }
+                        e.replace(e.getLeft().clone());
                     }
                     else
                     {
-                        e.getRight().accept(exec);
-                        if (exec.getResult()->isTrue())
-                        {
-                            types::InternalType * b = new types::Bool(1);
-                            e.replace(b->getExp(e.getLocation()));
-                            setResult(true);
-                            return;
-                        }
-                        else
-                        {
-                            e.replace(e.getLeft().clone());
-                        }
+                        types::InternalType * b = new types::Bool(0);
+                        e.replace(b->getExp(e.getLocation()));
+                        setResult(true);
+                        return;
                     }
                 }
             }
-        }
-
-        setResult(false);
-    }
-
-    void ConstantVisitor::visit(ast::LogicalOpExp & e)
-    {
-        visit(static_cast<ast::OpExp &>(e));
-    }
-
-    void ConstantVisitor::visit(ast::CallExp & e)
-    {
-        bool isConstant = false;
-
-        if (evalSymbols)
-        {
-            ast::SimpleVar & var = static_cast<ast::SimpleVar &>(e.getName());
-            const symbol::Symbol & sym = var.getSymbol();
-           if (symbol::Context::getInstance()->isOriginalSymbol(sym))
+            else if (oper == ast::OpExp::Oper::logicalShortCutOr || oper == ast::OpExp::Oper::logicalOr)
             {
-                const std::wstring & name = sym.getName();
-                ast::exps_t args = e.getArgs();
-
-                bool allConstant = true;
-                for (auto arg : args)
+                if (constL)
                 {
-                    arg->accept(*this);
-                    if (allConstant && !getResult())
+                    e.getLeft().accept(exec);
+                    if (exec.getResult()->isTrue())
                     {
-                        allConstant = false;
+                        types::InternalType * b = new types::Bool(1);
+                        e.replace(b->getExp(e.getLocation()));
+                        setResult(true);
+                        return;
+                    }
+                    else
+                    {
+                        e.replace(e.getRight().clone());
                     }
                 }
-
-                if (allConstant && Checkers::isConst(name, args.size()))
+                else
                 {
-                    if (name == L"argn")
+                    e.getRight().accept(exec);
+                    if (exec.getResult()->isTrue())
                     {
-                        if (parent && parent->getAnalyzer(sym)->analyze(*parent, lhs, e))
-                        {
-                            if (lhs == 1)
-                            {
-                                double val;
-                                parent->getResult().getConstant().getDblValue(val);
-                                e.replace(new ast::DoubleExp(e.getLocation(), val));
-                                isConstant = true;
-                            }
-                            else
-                            {
-                                double val;
-                                ast::exps_t exps;
-                                exps.reserve(2);
-                                std::vector<Result> & res = parent->getLHSContainer();
-                                res.front().getConstant().getDblValue(val);
-                                exps.push_back(new ast::DoubleExp(e.getLocation(), val));
-                                res.back().getConstant().getDblValue(val);
-                                exps.push_back(new ast::DoubleExp(e.getLocation(), val));
-                                e.replace(new ast::ArrayListExp(e.getLocation(), exps));
-                                isConstant = true;
-                            }
-                        }
+                        types::InternalType * b = new types::Bool(1);
+                        e.replace(b->getExp(e.getLocation()));
+                        setResult(true);
+                        return;
                     }
                     else
                     {
-                        isConstant = execAndReplace(e);
+                        e.replace(e.getLeft().clone());
                     }
                 }
+            }
+        }
+    }
+
+    setResult(false);
+}
+
+void ConstantVisitor::visit(ast::LogicalOpExp & e)
+{
+    visit(static_cast<ast::OpExp &>(e));
+}
+
+void ConstantVisitor::visit(ast::CallExp & e)
+{
+    bool isConstant = false;
 
-                if (parent && args.size() == 1)
+    if (evalSymbols)
+    {
+        ast::SimpleVar & var = static_cast<ast::SimpleVar &>(e.getName());
+        const symbol::Symbol & sym = var.getSymbol();
+        if (symbol::Context::getInstance()->isOriginalSymbol(sym))
+        {
+            const std::wstring & name = sym.getName();
+            ast::exps_t args = e.getArgs();
+
+            bool allConstant = true;
+            for (auto arg : args)
+            {
+                arg->accept(*this);
+                if (allConstant && !getResult())
                 {
-                    if (name == L"type" || name == L"inttype")
+                    allConstant = false;
+                }
+            }
+
+            if (allConstant && Checkers::isConst(name, args.size()))
+            {
+                if (name == L"argn")
+                {
+                    if (parent && parent->getAnalyzer(sym)->analyze(*parent, lhs, e))
                     {
-                        if (parent->getAnalyzer(sym)->analyze(*parent, 1, e))
+                        if (lhs == 1)
                         {
                             double val;
                             parent->getResult().getConstant().getDblValue(val);
                             e.replace(new ast::DoubleExp(e.getLocation(), val));
                             isConstant = true;
                         }
-                    }
-                    else if (name == L"typeof")
-                    {
-                        if (parent->getAnalyzer(sym)->analyze(*parent, 1, e))
+                        else
                         {
-                            std::wstring wstr;
-                            if (parent->getResult().getConstant().getStrValue(wstr))
-                            {
-                                e.replace(new ast::StringExp(e.getLocation(), wstr));
-                                isConstant = true;
-                            }
+                            double val;
+                            ast::exps_t exps;
+                            exps.reserve(2);
+                            std::vector<Result> & res = parent->getLHSContainer();
+                            res.front().getConstant().getDblValue(val);
+                            exps.push_back(new ast::DoubleExp(e.getLocation(), val));
+                            res.back().getConstant().getDblValue(val);
+                            exps.push_back(new ast::DoubleExp(e.getLocation(), val));
+                            e.replace(new ast::ArrayListExp(e.getLocation(), exps));
+                            isConstant = true;
                         }
                     }
-                    else if (name == L"isreal" || name == L"isscalar")
+                }
+                else
+                {
+                    isConstant = execAndReplace(e);
+                }
+            }
+
+            if (parent && args.size() == 1)
+            {
+                if (name == L"type" || name == L"inttype")
+                {
+                    if (parent->getAnalyzer(sym)->analyze(*parent, 1, e))
+                    {
+                        double val;
+                        parent->getResult().getConstant().getDblValue(val);
+                        e.replace(new ast::DoubleExp(e.getLocation(), val));
+                        isConstant = true;
+                    }
+                }
+                else if (name == L"typeof")
+                {
+                    if (parent->getAnalyzer(sym)->analyze(*parent, 1, e))
                     {
-                        if (parent->getAnalyzer(sym)->analyze(*parent, 1, e))
+                        std::wstring wstr;
+                        if (parent->getResult().getConstant().getStrValue(wstr))
                         {
-                            bool val;
-                            parent->getResult().getConstant().getBoolValue(val);
-                            e.replace(new ast::BoolExp(e.getLocation(), val));
+                            e.replace(new ast::StringExp(e.getLocation(), wstr));
                             isConstant = true;
                         }
                     }
                 }
-            }
-        }
-
-        setResult(isConstant);
-    }
-
-    void ConstantVisitor::visit(ast::MatrixExp & e)
-    {
-        const ast::exps_t & lines = e.getLines();
-        if (lines.empty())
-        {
-            setResult(execAndReplace(e));
-        }
-        else
-        {
-            for (auto line : lines)
-            {
-                const ast::exps_t & columns = static_cast<ast::MatrixLineExp *>(line)->getColumns();
-                for (auto column : columns)
+                else if (name == L"isreal" || name == L"isscalar")
                 {
-                    column->accept(*this);
-                    if (!getResult())
+                    if (parent->getAnalyzer(sym)->analyze(*parent, 1, e))
                     {
-                        return;
+                        bool val;
+                        parent->getResult().getConstant().getBoolValue(val);
+                        e.replace(new ast::BoolExp(e.getLocation(), val));
+                        isConstant = true;
                     }
                 }
             }
-            setResult(execAndReplace(e));
         }
     }
 
-    void ConstantVisitor::visit(ast::NotExp & e)
+    setResult(isConstant);
+}
+
+void ConstantVisitor::visit(ast::MatrixExp & e)
+{
+    const ast::exps_t & lines = e.getLines();
+    if (lines.empty())
     {
-        e.getExp().accept(*this);
-        if (getResult())
-        {
-            setResult(execAndReplace(e));
-        }
-        else
-        {
-            setResult(false);
-        }
+        setResult(execAndReplace(e));
     }
-
-    void ConstantVisitor::visit(ast::TransposeExp & e)
+    else
     {
-        e.getExp().accept(*this);
-        if (getResult())
+        for (auto line : lines)
         {
-            setResult(execAndReplace(e));
-        }
-        else
-        {
-            setResult(false);
+            const ast::exps_t & columns = static_cast<ast::MatrixLineExp *>(line)->getColumns();
+            for (auto column : columns)
+            {
+                column->accept(*this);
+                if (!getResult())
+                {
+                    return;
+                }
+            }
         }
+        setResult(execAndReplace(e));
     }
+}
 
-    void ConstantVisitor::visit(ast::CellExp & e)
+void ConstantVisitor::visit(ast::NotExp & e)
+{
+    e.getExp().accept(*this);
+    if (getResult())
     {
-        visit(static_cast<ast::MatrixExp &>(e));
+        setResult(execAndReplace(e));
     }
-
-    void ConstantVisitor::visit(ast::ListExp & e)
+    else
     {
-        e.getStart().accept(*this);
-        const bool startConst = getResult();
-        e.getStep().accept(*this);
-        const bool stepConst = getResult();
-        e.getEnd().accept(*this);
-        const bool endConst = getResult();
-
-        if (startConst && stepConst && endConst)
-        {
-            setResult(execAndReplace(e));
-        }
-        else
-        {
-            setResult(false);
-        }
+        setResult(false);
     }
+}
 
-    void ConstantVisitor::visit(ast::IfExp & e)
+void ConstantVisitor::visit(ast::TransposeExp & e)
+{
+    e.getExp().accept(*this);
+    if (getResult())
     {
+        setResult(execAndReplace(e));
     }
-
-    void ConstantVisitor::visit(ast::DollarVar & e)
+    else
     {
         setResult(false);
     }
+}
 
-    void ConstantVisitor::visit(ast::ColonVar & e)
-    {
-        setResult(false);
-    }
+void ConstantVisitor::visit(ast::CellExp & e)
+{
+    visit(static_cast<ast::MatrixExp &>(e));
+}
 
-    void ConstantVisitor::visit(ast::ArrayListVar & e)
-    {
-    }
+void ConstantVisitor::visit(ast::ListExp & e)
+{
+    e.getStart().accept(*this);
+    const bool startConst = getResult();
+    e.getStep().accept(*this);
+    const bool stepConst = getResult();
+    e.getEnd().accept(*this);
+    const bool endConst = getResult();
 
-    void ConstantVisitor::visit(ast::DoubleExp & e)
+    if (startConst && stepConst && endConst)
     {
-        setResult(true);
+        setResult(execAndReplace(e));
     }
-
-    void ConstantVisitor::visit(ast::BoolExp & e)
+    else
     {
-        setResult(true);
+        setResult(false);
     }
+}
 
-    void ConstantVisitor::visit(ast::StringExp & e)
-    {
-        setResult(true);
-    }
+void ConstantVisitor::visit(ast::IfExp & e)
+{
+}
 
-    void ConstantVisitor::visit(ast::CommentExp & e)
-    {
-        // ignored
-    }
+void ConstantVisitor::visit(ast::DollarVar & e)
+{
+    setResult(false);
+}
 
-    void ConstantVisitor::visit(ast::NilExp & e)
-    {
-        // nothing to do
-    }
+void ConstantVisitor::visit(ast::ColonVar & e)
+{
+    setResult(false);
+}
 
-    void ConstantVisitor::visit(ast::CellCallExp & e)
-    {
-        setResult(false);
-    }
+void ConstantVisitor::visit(ast::ArrayListVar & e)
+{
+}
 
-    void ConstantVisitor::visit(ast::AssignExp & e)
-    {
-    }
+void ConstantVisitor::visit(ast::DoubleExp & e)
+{
+    setResult(true);
+}
 
-    void ConstantVisitor::visit(ast::WhileExp & e)
-    {
-    }
+void ConstantVisitor::visit(ast::BoolExp & e)
+{
+    setResult(true);
+}
 
-    void ConstantVisitor::visit(ast::ForExp & e)
-    {
-    }
+void ConstantVisitor::visit(ast::StringExp & e)
+{
+    setResult(true);
+}
 
-    void ConstantVisitor::visit(ast::BreakExp & e)
-    {
-        // nothing to do
-    }
+void ConstantVisitor::visit(ast::CommentExp & e)
+{
+    // ignored
+}
 
-    void ConstantVisitor::visit(ast::ContinueExp & e)
-    {
-        // nothing to do
-    }
+void ConstantVisitor::visit(ast::NilExp & e)
+{
+    // nothing to do
+}
 
-    void ConstantVisitor::visit(ast::TryCatchExp & e)
-    {
-    }
+void ConstantVisitor::visit(ast::CellCallExp & e)
+{
+    setResult(false);
+}
 
-    void ConstantVisitor::visit(ast::SelectExp & e)
-    {
-    }
+void ConstantVisitor::visit(ast::AssignExp & e)
+{
+}
 
-    void ConstantVisitor::visit(ast::CaseExp & e)
-    {
-    }
+void ConstantVisitor::visit(ast::WhileExp & e)
+{
+}
 
-    void ConstantVisitor::visit(ast::ReturnExp & e)
-    {
-    }
+void ConstantVisitor::visit(ast::ForExp & e)
+{
+}
 
-    void ConstantVisitor::visit(ast::FieldExp & e)
-    {
-    }
+void ConstantVisitor::visit(ast::BreakExp & e)
+{
+    // nothing to do
+}
 
-    void ConstantVisitor::visit(ast::MatrixLineExp & e)
-    {
-    }
+void ConstantVisitor::visit(ast::ContinueExp & e)
+{
+    // nothing to do
+}
 
-    void ConstantVisitor::visit(ast::SeqExp & e)
-    {
-    }
+void ConstantVisitor::visit(ast::TryCatchExp & e)
+{
+}
 
-    void ConstantVisitor::visit(ast::ArrayListExp & e)
-    {
-    }
+void ConstantVisitor::visit(ast::SelectExp & e)
+{
+}
 
-    void ConstantVisitor::visit(ast::AssignListExp & e)
-    {
-    }
+void ConstantVisitor::visit(ast::CaseExp & e)
+{
+}
 
-    void ConstantVisitor::visit(ast::VarDec & e)
-    {
-    }
+void ConstantVisitor::visit(ast::ReturnExp & e)
+{
+}
 
-    void ConstantVisitor::visit(ast::FunctionDec & e)
-    {
-    }
+void ConstantVisitor::visit(ast::FieldExp & e)
+{
+}
 
-    void ConstantVisitor::visit(ast::OptimizedExp & e)
-    {
-    }
+void ConstantVisitor::visit(ast::MatrixLineExp & e)
+{
+}
 
-    void ConstantVisitor::visit(ast::MemfillExp & e)
-    {
-    }
+void ConstantVisitor::visit(ast::SeqExp & e)
+{
+}
 
-    void ConstantVisitor::visit(ast::DAXPYExp & e)
-    {
-    }
+void ConstantVisitor::visit(ast::ArrayListExp & e)
+{
+}
 
-    void ConstantVisitor::visit(ast::IntSelectExp & e)
-    {
-    }
+void ConstantVisitor::visit(ast::AssignListExp & e)
+{
+}
 
-    void ConstantVisitor::visit(ast::StringSelectExp & e)
-    {
-    }
-    
-    std::unordered_set<std::wstring> ConstantVisitor::init()
-    {
-        std::unordered_set<std::wstring> _constants;
-        _constants.emplace(L"%pi");
-        _constants.emplace(L"%eps");
-        _constants.emplace(L"%e");
-        _constants.emplace(L"%i");
-        _constants.emplace(L"%nan");
-        _constants.emplace(L"%inf");
-        _constants.emplace(L"%t");
-        _constants.emplace(L"%f");
-        _constants.emplace(L"%T");
-        _constants.emplace(L"%F");
-        _constants.emplace(L"SCI");
-        _constants.emplace(L"WSCI");
-        _constants.emplace(L"SCIHOME");
-        _constants.emplace(L"TMPDIR");
-
-        return _constants;
-    }
+void ConstantVisitor::visit(ast::VarDec & e)
+{
+}
+
+void ConstantVisitor::visit(ast::FunctionDec & e)
+{
+}
+
+void ConstantVisitor::visit(ast::OptimizedExp & e)
+{
+}
+
+void ConstantVisitor::visit(ast::MemfillExp & e)
+{
+}
+
+void ConstantVisitor::visit(ast::DAXPYExp & e)
+{
+}
+
+void ConstantVisitor::visit(ast::IntSelectExp & e)
+{
+}
+
+void ConstantVisitor::visit(ast::StringSelectExp & e)
+{
+}
+
+std::unordered_set<std::wstring> ConstantVisitor::init()
+{
+    std::unordered_set<std::wstring> _constants;
+    _constants.emplace(L"%pi");
+    _constants.emplace(L"%eps");
+    _constants.emplace(L"%e");
+    _constants.emplace(L"%i");
+    _constants.emplace(L"%nan");
+    _constants.emplace(L"%inf");
+    _constants.emplace(L"%t");
+    _constants.emplace(L"%f");
+    _constants.emplace(L"%T");
+    _constants.emplace(L"%F");
+    _constants.emplace(L"SCI");
+    _constants.emplace(L"WSCI");
+    _constants.emplace(L"SCIHOME");
+    _constants.emplace(L"TMPDIR");
+
+    return _constants;
+}
 }
index 306852b..c7cda6f 100644 (file)
 
 namespace analysis
 {
-    
-    DataManager::DataManager() : id(0)
-    {
-        current = root = new Block(this);
-    }
 
-    DataManager::~DataManager()
-    {
-        for (const auto d : data)
-        {
-            delete d;
-        }
-        delete root;
-        for (const auto & p : macroDefCache)
-        {
-            delete p.second;
-        }
-    }
+DataManager::DataManager() : id(0)
+{
+    current = root = new Block(this);
+}
 
-    GVN & DataManager::getGVN()
+DataManager::~DataManager()
+{
+    for (const auto d : data)
     {
-        return current->getGVN();
+        delete d;
     }
-
-    GVN & DataManager::getDefaultGVN()
+    delete root;
+    for (const auto & p : macroDefCache)
     {
-        return gvn;
+        delete p.second;
     }
+}
 
-    MacroDef * DataManager::getMacroDef(types::Macro * macro)
-    {
-        auto i = macroDefCache.find(macro);
-        if (i == macroDefCache.end())
-        {
-            i = macroDefCache.emplace(macro, new ExistingMacroDef(*macro)).first;
-        }
-        return i->second;
-    }
+GVN & DataManager::getGVN()
+{
+    return current->getGVN();
+}
 
-    void DataManager::addGlobal(const symbol::Symbol & sym)
-    {
-        globals.emplace(sym);
-    }
+GVN & DataManager::getDefaultGVN()
+{
+    return gvn;
+}
 
-    void DataManager::registerData(Data * _data, int line, char * file)
+MacroDef * DataManager::getMacroDef(types::Macro * macro)
+{
+    auto i = macroDefCache.find(macro);
+    if (i == macroDefCache.end())
     {
-        if (_data)
-        {
-            /*              bool ok = true;
-                            for (const auto d : data)
-                            {
-                            if (d == _data)
-                            {
-                            ok =  false;
-                            break;
-                            }
-                            }
-
-                            std::cout << "ptr added=" << _data << " line:" << line << " file:" << file << " doubloon:" << ok << std::endl;
-            */
-            data.push_back(_data);
-        }
+        i = macroDefCache.emplace(macro, new ExistingMacroDef(*macro)).first;
     }
+    return i->second;
+}
 
-    int DataManager::getTmpId(const TIType & type, const bool isAnInt)
-    {
-        return current->getTmpId(type, isAnInt);
-    }
+void DataManager::addGlobal(const symbol::Symbol & sym)
+{
+    globals.emplace(sym);
+}
 
-    void DataManager::releaseTmp(const int id)
+void DataManager::registerData(Data * _data, int line, char * file)
+{
+    if (_data)
     {
-        current->releaseTmp(id);
+        /*              bool ok = true;
+                        for (const auto d : data)
+                        {
+                        if (d == _data)
+                        {
+                        ok =  false;
+                        break;
+                        }
+                        }
+
+                        std::cout << "ptr added=" << _data << " line:" << line << " file:" << file << " doubloon:" << ok << std::endl;
+        */
+        data.push_back(_data);
     }
+}
 
-    Info & DataManager::read(const symbol::Symbol & sym, ast::Exp * exp)
-    {
-        return current->addRead(sym, exp);
-    }
+int DataManager::getTmpId(const TIType & type, const bool isAnInt)
+{
+    return current->getTmpId(type, isAnInt);
+}
 
-    Info & DataManager::write(const symbol::Symbol & sym, const TIType & Rtype, ast::Exp * exp)
-    {
-        return current->addWrite(sym, Rtype, exp);
-    }
+void DataManager::releaseTmp(const int id)
+{
+    current->releaseTmp(id);
+}
 
-    Info & DataManager::define(const symbol::Symbol & sym, const TIType & Rtype, const bool isAnInt, ast::Exp * exp)
-    {
-        return current->addDefine(sym, Rtype, isAnInt, exp);
-    }
+Info & DataManager::read(const symbol::Symbol & sym, ast::Exp * exp)
+{
+    return current->addRead(sym, exp);
+}
 
-    Info & DataManager::share(const symbol::Symbol & Lsym, const symbol::Symbol & Rsym, const TIType & Rtype, ast::Exp * exp)
-    {
-        return current->addShare(Lsym, Rsym, Rtype, exp);
-    }
+Info & DataManager::write(const symbol::Symbol & sym, const TIType & Rtype, ast::Exp * exp)
+{
+    return current->addWrite(sym, Rtype, exp);
+}
 
-    Info & DataManager::clear(const symbol::Symbol & sym, ast::Exp * exp)
-    {
-        return current->addClear(sym, exp);
-    }
+Info & DataManager::define(const symbol::Symbol & sym, const TIType & Rtype, const bool isAnInt, ast::Exp * exp)
+{
+    return current->addDefine(sym, Rtype, isAnInt, exp);
+}
 
-    Info & DataManager::macrodef(ast::Exp * exp)
-    {
-        return current->addMacroDef(static_cast<ast::FunctionDec *>(exp));
-    }
+Info & DataManager::share(const symbol::Symbol & Lsym, const symbol::Symbol & Rsym, const TIType & Rtype, ast::Exp * exp)
+{
+    return current->addShare(Lsym, Rsym, Rtype, exp);
+}
 
-    std::vector<TIType> DataManager::call(AnalysisVisitor & visitor, const unsigned int lhs, const symbol::Symbol & sym, std::vector<TIType> & in, ast::CallExp * callexp)
-    {
-        return current->addCall(visitor, lhs, sym, in, callexp);
-    }
+Info & DataManager::clear(const symbol::Symbol & sym, ast::Exp * exp)
+{
+    return current->addClear(sym, exp);
+}
 
-    void DataManager::addBlock(Block::BlockKind kind, ast::Exp * exp)
-    {
-        current = current->addBlock(++id, kind, exp);
-    }
+Info & DataManager::macrodef(ast::Exp * exp)
+{
+    return current->addMacroDef(static_cast<ast::FunctionDec *>(exp));
+}
 
-    Block * DataManager::getCurrent()
-    {
-        return current;
-    }
+std::vector<TIType> DataManager::call(AnalysisVisitor & visitor, const unsigned int lhs, const symbol::Symbol & sym, std::vector<TIType> & in, ast::CallExp * callexp)
+{
+    return current->addCall(visitor, lhs, sym, in, callexp);
+}
 
-    void DataManager::finalizeBlock()
-    {
+void DataManager::addBlock(Block::BlockKind kind, ast::Exp * exp)
+{
+    current = current->addBlock(++id, kind, exp);
+}
+
+Block * DataManager::getCurrent()
+{
+    return current;
+}
+
+void DataManager::finalizeBlock()
+{
 #ifndef DEBUG_DATAMANAGER
-        current->finalize();
+    current->finalize();
 #endif
-        current = current->parent;
-    }
+    current = current->parent;
+}
 
-    bool DataManager::requiresAnotherTrip()
-    {
-        return current->requiresAnotherTrip();
-    }
+bool DataManager::requiresAnotherTrip()
+{
+    return current->requiresAnotherTrip();
+}
 
-    void DataManager::pushFunction(FunctionBlock * fblock)
-    {
-        callStack.push(fblock);
-    }
+void DataManager::pushFunction(FunctionBlock * fblock)
+{
+    callStack.push(fblock);
+}
 
-    FunctionBlock * DataManager::poptopFunction()
-    {
-        FunctionBlock * fblock = callStack.top();
-        callStack.pop();
-        return fblock;
-    }
+FunctionBlock * DataManager::poptopFunction()
+{
+    FunctionBlock * fblock = callStack.top();
+    callStack.pop();
+    return fblock;
+}
 
-    FunctionBlock * DataManager::topFunction()
+FunctionBlock * DataManager::topFunction()
+{
+    if (callStack.empty())
     {
-        if (callStack.empty())
-        {
-            return nullptr;
-        }
-        return callStack.top();
+        return nullptr;
     }
+    return callStack.top();
+}
 
-    void DataManager::popFunction()
-    {
-        callStack.pop();
-    }
+void DataManager::popFunction()
+{
+    callStack.pop();
+}
 
-    TIType DataManager::getSymInScilabContext(GVN & gvn, const symbol::Symbol & sym, bool & exists)
-    {
-        types::InternalType * pIT;
-        return getSymInScilabContext(gvn, sym, exists, pIT);
-    }
+TIType DataManager::getSymInScilabContext(GVN & gvn, const symbol::Symbol & sym, bool & exists)
+{
+    types::InternalType * pIT;
+    return getSymInScilabContext(gvn, sym, exists, pIT);
+}
 
-    TIType DataManager::getSymInScilabContext(GVN & gvn, const symbol::Symbol & sym, types::InternalType *& pIT)
-    {
-        bool exists;
-        return getSymInScilabContext(gvn, sym, exists, pIT);
-    }
+TIType DataManager::getSymInScilabContext(GVN & gvn, const symbol::Symbol & sym, types::InternalType *& pIT)
+{
+    bool exists;
+    return getSymInScilabContext(gvn, sym, exists, pIT);
+}
 
-    TIType DataManager::getSymInScilabContext(GVN & gvn, const symbol::Symbol & sym, bool & exists, types::InternalType *& pIT)
+TIType DataManager::getSymInScilabContext(GVN & gvn, const symbol::Symbol & sym, bool & exists, types::InternalType *& pIT)
+{
+    pIT = symbol::Context::getInstance()->get(sym);
+    if (pIT)
     {
-        pIT = symbol::Context::getInstance()->get(sym);
-        if (pIT)
+        exists = true;
+        if (pIT->isGenericType())
         {
-            exists = true;
-            if (pIT->isGenericType())
+            types::GenericType * pGT = static_cast<types::GenericType *>(pIT);
+            switch (pIT->getType())
             {
-                types::GenericType * pGT = static_cast<types::GenericType *>(pIT);
-                switch (pIT->getType())
-                {
                 case types::InternalType::ScilabInt8:
                     return TIType(gvn, TIType::Type::INT8, pGT->getRows(), pGT->getCols());
                 case types::InternalType::ScilabUInt8:
@@ -242,12 +242,12 @@ namespace analysis
                     return TIType(gvn, TIType::Type::SPARSE, pGT->getRows(), pGT->getCols());
                 default:
                     return TIType(gvn, TIType::Type::UNKNOWN, pGT->getRows(), pGT->getCols());
-                }
             }
-            else if (pIT->isCallable())
+        }
+        else if (pIT->isCallable())
+        {
+            switch (pIT->getType())
             {
-                switch (pIT->getType())
-                {
                 case types::InternalType::ScilabFunction:
                     return TIType(gvn, TIType::Type::FUNCTION);
                 case types::InternalType::ScilabMacro:
@@ -256,52 +256,52 @@ namespace analysis
                     return TIType(gvn, TIType::Type::MACROFILE);
                 case types::InternalType::ScilabLibrary:
                     return TIType(gvn, TIType::Type::LIBRARY);
-                }
             }
         }
-
-        exists = false;
-        return TIType(gvn);
     }
 
-    TIType DataManager::getType(const symbol::Symbol & sym, const bool global)
+    exists = false;
+    return TIType(gvn);
+}
+
+TIType DataManager::getType(const symbol::Symbol & sym, const bool global)
+{
+    Block * parent = getCurrent();
+    tools::SymbolMap<Info>::iterator it;
+    Block * block = parent->getDefBlock(sym, it, global);
+    if (block)
     {
-        Block * parent = getCurrent();
-        std::map<symbol::Symbol, Info>::iterator it;
-        Block * block = parent->getDefBlock(sym, it, global);
-        if (block)
-        {
-            return it->second.type;
-        }
-        else
-        {
-            bool exists;
-            return DataManager::getSymInScilabContext(getGVN(), sym, exists);
-        }
+        return it->second.type;
     }
-
-    Info & DataManager::getInfo(const symbol::Symbol & sym)
+    else
     {
-        std::map<symbol::Symbol, Info>::iterator it;
-        Block * block = current->getDefBlock(sym, it, false);
-        if (block)
-        {
-            return it->second;
-        }
-
-        // The sym is not in this DataManager... try in the Scilab's context
-        return current->setDefaultData(sym);
+        bool exists;
+        return DataManager::getSymInScilabContext(getGVN(), sym, exists);
     }
+}
 
-    std::wostream & operator<<(std::wostream & out, const DataManager & dm)
+Info & DataManager::getInfo(const symbol::Symbol & sym)
+{
+    tools::SymbolMap<Info>::iterator it;
+    Block * block = current->getDefBlock(sym, it, false);
+    if (block)
     {
-        out << L"DataManager:" << std::endl
-            << L"Globals: ";
+        return it->second;
+    }
 
-        tools::printSet(dm.globals, out);
-        out << std::endl << *dm.root;
+    // The sym is not in this DataManager... try in the Scilab's context
+    return current->setDefaultData(sym);
+}
+
+std::wostream & operator<<(std::wostream & out, const DataManager & dm)
+{
+    out << L"DataManager:" << std::endl
+        << L"Globals: ";
+
+    tools::printSet(dm.globals, out);
+    out << std::endl << *dm.root;
+
+    return out;
+}
 
-        return out;
-    }
-    
 } // namespace analysis
index 292c20b..db67c60 100644 (file)
 namespace analysis
 {
 
-    FunctionBlock::FunctionBlock(const unsigned int id, Block * parent, ast::Exp * exp) : Block(id, parent, exp), constraintManager(*this, dm->topFunction())
-    {
-        gvn = &fgvn;
-        dm->pushFunction(this);
-    }
+FunctionBlock::FunctionBlock(const unsigned int id, Block * parent, ast::Exp * exp) : Block(id, parent, exp), loopAnalyzer(exp), constraintManager(*this, dm->topFunction())
+{
+    gvn = &fgvn;
+    dm->pushFunction(this);
+    //std::wcerr << L"Loop analyze:" << loopAnalyzer << std::endl;
+}
 
-    bool FunctionBlock::addIn(const TITypeSignatureTuple & tuple, const std::vector<GVN::Value *> & values)
+bool FunctionBlock::addIn(const TITypeSignatureTuple & tuple, const std::vector<GVN::Value *> & values)
+{
+    std::vector<TITypeSignature>::const_iterator i = tuple.types.begin();
+    for (const auto & sym : in)
     {
-        std::vector<TITypeSignature>::const_iterator i = tuple.types.begin();
-        for (const auto & sym : in)
-        {
-            Info & info = addSym(sym, new Data(false, sym));
-            info.type = TIType(fgvn, i->type, i->scalar);
-            dm->registerData(info.data);//, __LINE__, __FILE__);
-            ++i;
-        }
-
-        for (const auto & sym : globals)
-        {
-            Info & info = addSym(sym, new Data(false, sym));
-            info.type = TIType(fgvn, i->type, i->scalar);
-            dm->registerData(info.data);//, __LINE__, __FILE__);
-            ++i;
-        }
-        inValues = values;
-       maxVarId = fgvn.getCurrentValue() - 1;
-
-        return true;
+        Info & info = addSym(sym, new Data(false, sym));
+        info.type = TIType(fgvn, i->type, i->scalar);
+        dm->registerData(info.data);//, __LINE__, __FILE__);
+        ++i;
     }
 
-    void FunctionBlock::addGlobal(const symbol::Symbol & sym)
+    for (const auto & sym : globals)
     {
-        //globals.emplace(sym);
-        Block::addGlobal(sym);
+        Info & info = addSym(sym, new Data(false, sym));
+        info.type = TIType(fgvn, i->type, i->scalar);
+        dm->registerData(info.data);//, __LINE__, __FILE__);
+        ++i;
     }
+    inValues = values;
+    maxVarId = fgvn.getCurrentValue() - 1;
 
-    void FunctionBlock::setGlobals(const std::set<symbol::Symbol> & v)
-    {
-       //globals = v; => bug on mac
-       std::copy(v.begin(), v.end(), std::inserter(globals, globals.begin()));
-    }
+    return true;
+}
+
+void FunctionBlock::addGlobal(const symbol::Symbol & sym)
+{
+    //globals.emplace(sym);
+    Block::addGlobal(sym);
+}
+
+void FunctionBlock::setGlobals(const tools::SymbolOrdSet & v)
+{
+    //globals = v; => bug on mac
+    std::copy(v.begin(), v.end(), std::inserter(globals, globals.begin()));
+}
 
 /*    TITypeSignatureTuple FunctionBlock::getGlobals(std::vector<symbol::Symbol> & v)
     {
@@ -73,7 +74,7 @@ namespace analysis
         for (const auto & sym : globals)
         {
             v.emplace_back(sym);
-            std::map<symbol::Symbol, Info>::iterator it;
+            tools::SymbolMap<Info>::iterator it;
             Block * block = parent->getDefBlock(sym, it);
             if (block)
             {
@@ -90,192 +91,192 @@ namespace analysis
         return tuple;
     }
 */
-    MacroOut FunctionBlock::getOuts()
+MacroOut FunctionBlock::getOuts()
+{
+    MacroOut mo;
+    mo.maxVarId = maxVarId;
+    std::vector<TIType> & v = mo.tuple.types;
+    v.reserve(lhs);
+    unsigned int i = 0;
+    for (std::vector<symbol::Symbol>::const_iterator s = out.begin(); i < lhs; ++i, ++s)
     {
-        MacroOut mo;
-       mo.maxVarId = maxVarId;
-        std::vector<TIType> & v = mo.tuple.types;
-        v.reserve(lhs);
-        unsigned int i = 0;
-        for (std::vector<symbol::Symbol>::const_iterator s = out.begin(); i < lhs; ++i, ++s)
+        tools::SymbolMap<Info>::iterator it;
+        Block * block = getDefBlock(*s, it, false);
+        if (block == this)
         {
-            std::map<symbol::Symbol, Info>::iterator it;
-            Block * block = getDefBlock(*s, it, false);
-            if (block == this)
+            v.emplace_back(it->second.type);
+        }
+        else
+        {
+            addGlobal(*s);
+            if (block)
             {
                 v.emplace_back(it->second.type);
             }
             else
             {
-                addGlobal(*s);
-                if (block)
-                {
-                    v.emplace_back(it->second.type);
-                }
-                else
-                {
-                    // TODO: if exists is false then it is an error
-                    bool exists;
-                    v.emplace_back(DataManager::getSymInScilabContext(fgvn, *s, exists));
-                }
+                // TODO: if exists is false then it is an error
+                bool exists;
+                v.emplace_back(DataManager::getSymInScilabContext(fgvn, *s, exists));
             }
         }
-
-        return mo;
     }
 
-    void FunctionBlock::finalize()
+    return mo;
+}
+
+void FunctionBlock::finalize()
+{
+    dm->popFunction();
+
+    for (unsigned int i = 0; i != lhs; ++i)
     {
-        dm->popFunction();
+        auto it = symMap.find(out[i]);
+        if (it != symMap.end())
+        {
+            const TIType & type = it->second.type;
+            if (type.isscalar())
+            {
+                types_out.emplace_back(out[i], TypeLocal(type.type, 1, 1, false));
+            }
+            else
+            {
+                types_out.emplace_back(out[i], TypeLocal(type.type, -1, -1, false));
+            }
+        }
+        else
+        {
+            types_out.emplace_back(out[i], TypeLocal(TIType::UNKNOWN, -1, -1, false));
+        }
 
-       for (unsigned int i = 0; i != lhs; ++i)
-       {
-           auto it = symMap.find(out[i]);
-           if (it != symMap.end())
-           {
-               const TIType & type = it->second.type;
-               if (type.isscalar())
-               {
-                   types_out.emplace_back(out[i], TypeLocal(type.type, 1, 1, false));
-               }
-               else
-               {
-                   types_out.emplace_back(out[i], TypeLocal(type.type, -1, -1, false));
-               }
-           }
-           else
-           {
-               types_out.emplace_back(out[i], TypeLocal(TIType::UNKNOWN, -1, -1, false));
-           }
-           
-           auto jt = locals.find(out[i]);
-           if (jt != locals.end())
-           {
-               jt->second.erase(types_out.back().second);
-               if (jt->second.empty())
-               {
-                   locals.erase(jt);
-               }
-           }
-       }
+        auto jt = locals.find(out[i]);
+        if (jt != locals.end())
+        {
+            jt->second.erase(types_out.back().second);
+            if (jt->second.empty())
+            {
+                locals.erase(jt);
+            }
+        }
     }
+}
 
-    void FunctionBlock::addLocal(const symbol::Symbol & sym, const TIType & type, const bool isAnInt)
+void FunctionBlock::addLocal(const symbol::Symbol & sym, const TIType & type, const bool isAnInt)
+{
+    auto i = locals.find(sym);
+    if (i == locals.end())
     {
-       auto i = locals.find(sym);
-       if (i == locals.end())
-       {
-           i = locals.emplace(sym, std::set<TypeLocal>()).first;
-       }
-
-       i->second.emplace(TypeLocal::get(type, isAnInt));
+        i = locals.emplace(sym, std::set<TypeLocal>()).first;
     }
 
-    int FunctionBlock::getTmpId(const TIType & type, const bool isAnInt)
+    i->second.emplace(TypeLocal::get(type, isAnInt));
+}
+
+int FunctionBlock::getTmpId(const TIType & type, const bool isAnInt)
+{
+    return tempManager.getTmp(type, isAnInt);
+}
+
+void FunctionBlock::releaseTmp(const int id)
+{
+    tempManager.releaseTmp(id);
+}
+
+void FunctionBlock::setInOut(MacroDef * macrodef, const unsigned int rhs, const std::vector<TIType> & _in)
+{
+    in = macrodef->getIn();
+    out = macrodef->getOut();
+
+    for (unsigned int i = 0; i != rhs; ++i)
     {
-       return tempManager.getTmp(type, isAnInt);
+        if (_in[i].isscalar())
+        {
+            types_in.emplace_back(in[i], TypeLocal(_in[i].type, 1, 1, false));
+        }
+        else
+        {
+            types_in.emplace_back(in[i], TypeLocal(_in[i].type, -1, -1, false));
+        }
     }
-    
-    void FunctionBlock::releaseTmp(const int id)
+}
+
+Block * FunctionBlock::getDefBlock(const symbol::Symbol & sym, tools::SymbolMap<Info>::iterator & it, const bool global)
+{
+    it = symMap.find(sym);
+    if (it == symMap.end())
     {
-       tempManager.releaseTmp(id);
+        if (!global && globals.find(sym) == globals.end())
+        {
+            // we have looked for a symbol which is not in this function
+            // so we add it and give it an unknown type
+            it = symMap.emplace(sym, new Data(false, sym)).first;
+            Info & info = it->second;
+            info.local = Info::Local::INFO_UNKNOWN;
+            info.type = TIType(fgvn);
+            dm->registerData(info.data);
+        }
+        else
+        {
+            return parent->getDefBlock(sym, it, true);
+        }
     }
+    return this;
+}
 
-    void FunctionBlock::setInOut(MacroDef * macrodef, const unsigned int rhs, const std::vector<TIType> & _in)
+std::wostream & operator<<(std::wostream & out, const FunctionBlock & fblock)
+{
+    out << L"Function " << fblock.name << L'\n'
+        << L" -LHS: " << fblock.lhs << L'\n'
+        << L" -RHS: " << fblock.rhs << L'\n'
+        << L" -in:" << L'\n';
+    for (const auto & p : fblock.types_in)
     {
-        in = macrodef->getIn();
-        out = macrodef->getOut();
+        out << L"   -" << p.first << L" -> " << p.second << L'\n';
+    }
 
-       for (unsigned int i = 0; i != rhs; ++i)
-       {
-           if (_in[i].isscalar())
-           {
-               types_in.emplace_back(in[i], TypeLocal(_in[i].type, 1, 1, false));
-           }
-           else
-           {
-               types_in.emplace_back(in[i], TypeLocal(_in[i].type, -1, -1, false));
-           }
-       }
+    out << L'\n'
+        << L" -out:" << L'\n';
+    for (const auto & p : fblock.types_out)
+    {
+        out << L"   -" << p.first << L" -> " << p.second << L'\n';
     }
-    
-    Block * FunctionBlock::getDefBlock(const symbol::Symbol & sym, std::map<symbol::Symbol, Info>::iterator & it, const bool global)
+    out << L'\n';
+    if (fblock.locals.empty())
     {
-       it = symMap.find(sym);
-       if (it == symMap.end())
-       {
-           if (!global && globals.find(sym) == globals.end())
-           {
-               // we have looked for a symbol which is not in this function
-               // so we add it and give it an unknown type
-               it = symMap.emplace(sym, new Data(false, sym)).first;
-               Info & info = it->second;
-               info.local = Info::Local::INFO_UNKNOWN;
-               info.type = TIType(fgvn);
-               dm->registerData(info.data);
-           }
-           else
-           {
-               return parent->getDefBlock(sym, it, true);
-           }
-       }
-       return this;
+        out << L" -locals: none" << L'\n';
     }
-
-    std::wostream & operator<<(std::wostream & out, const FunctionBlock & fblock)
+    else
     {
-       out << L"Function " << fblock.name << L'\n'
-           << L" -LHS: " << fblock.lhs << L'\n'
-           << L" -RHS: " << fblock.rhs << L'\n'
-           << L" -in:" << L'\n';
-       for (const auto & p : fblock.types_in)
-       {
-           out << L"   -" << p.first << L" -> " << p.second << L'\n';
-       }
-
-       out << L'\n'
-           << L" -out:" << L'\n';
-       for (const auto & p : fblock.types_out)
-       {
-           out << L"   -" << p.first << L" -> " << p.second << L'\n';
-       }
-       out << L'\n';
-       if (fblock.locals.empty())
-       {
-           out << L" -locals: none" << L'\n';
-       }
-       else
-       {
-           out << L" -locals:" << L'\n';
-           for (const auto & p : fblock.locals)
-           {
-               out << L"   -" << p.first << L" -> ";
-               tools::printSet(p.second, out);
-               out << L'\n';
-           }
-       }
+        out << L" -locals:" << L'\n';
+        for (const auto & p : fblock.locals)
+        {
+            out << L"   -" << p.first << L" -> ";
+            tools::printSet(p.second, out);
+            out << L'\n';
+        }
+    }
 
-       out << L'\n';
-       const std::map<TypeLocal, std::stack<int>> & temps = fblock.getTemp();
-       if (temps.empty())
-       {
-           out << L" -temps: none" << L'\n';
-       }
-       else
-       {
-           out << L" -temps:" << L'\n';
-           for (const auto & p : temps)
-           {
-               out << L"   -" << p.first << L" -> " << p.second.size() << L'\n';
-           }
-       }
+    out << L'\n';
+    const std::map<TypeLocal, std::stack<int>> & temps = fblock.getTemp();
+    if (temps.empty())
+    {
+        out << L" -temps: none" << L'\n';
+    }
+    else
+    {
+        out << L" -temps:" << L'\n';
+        for (const auto & p : temps)
+        {
+            out << L"   -" << p.first << L" -> " << p.second.size() << L'\n';
+        }
+    }
 
-       //ast::PrintVisitor pv(out, true, false);
-       //fblock.exp->accept(pv);
+    //ast::PrintVisitor pv(out, true, false);
+    //fblock.exp->accept(pv);
 
-       ast::DebugVisitor dv(out);
-       fblock.exp->accept(dv);
+    ast::DebugVisitor dv(out);
+    fblock.exp->accept(dv);
 
-       return out;
-    }
+    return out;
+}
 }
index 0ad42d7..affcc20 100644 (file)
 namespace analysis
 {
 
-    void GlobalsCollector::collect(MacroDef & macrodef)
-    {
-        GlobalsCollector gc(macrodef);
-        gc.collect();
-       //gc.print_info();
-    }
+void GlobalsCollector::collect(MacroDef & macrodef)
+{
+    GlobalsCollector(macrodef).collect();
+}
 
-    const std::set<symbol::Symbol> & GlobalsCollector::getGlobals() const
-    {
-        return globals;
-    }
+const tools::SymbolOrdSet & GlobalsCollector::getGlobals() const
+{
+    return globals;
+}
 
-    std::wostream & operator<<(std::wostream & out, const GlobalsCollector & gc)
-    {
-        out << L"name: " << gc.macrodef.getName() << std::endl
-            << L" -out: ";
-        tools::printSet(gc.macrodef.getOut(), out);
-        out << std::endl
-            << L" -in: ";
-        tools::printSet(gc.macrodef.getIn(), out);
-        out << std::endl
-            << L" -locals: ";
-        tools::printSet(gc.locals, out);
-        out << std::endl
-            << L" -globals: ";
-        tools::printSet(gc.globals, out);
-
-        return out;
-    }
+std::wostream & operator<<(std::wostream & out, const GlobalsCollector & gc)
+{
+    out << L"name: " << gc.macrodef.getName() << std::endl
+        << L" -out: ";
+    tools::printSet(gc.macrodef.getOut(), out);
+    out << std::endl
+        << L" -in: ";
+    tools::printSet(gc.macrodef.getIn(), out);
+    out << std::endl
+        << L" -locals: ";
+    tools::printSet(gc.locals, out);
+    out << std::endl
+        << L" -globals: ";
+    tools::printSet(gc.globals, out);
+
+    return out;
+}
+
+void GlobalsCollector::print_info()
+{
+    std::wcout << L"Globals collection: " << *static_cast<Chrono *>(this) << std::endl
+               << *this << std::endl;
+}
 
-    void GlobalsCollector::print_info()
+void GlobalsCollector::collect()
+{
+    start_chrono();
+
+    for (const auto arg : macrodef.getIn())
     {
-        std::wcout << L"Globals collection: " << *static_cast<Chrono *>(this) << std::endl
-                  << *this << std::endl;
+        locals.emplace(arg);
     }
 
-    void GlobalsCollector::collect()
-    {
-        start_chrono();
+    macrodef.getBody().accept(*this);
 
-        for (const auto arg : macrodef.getIn())
+    for (const auto & out : macrodef.getOut())
+    {
+        if (locals.find(out) == locals.end())
         {
-            locals.emplace(arg);
+            globals.emplace(out);
         }
+    }
 
-        macrodef.getBody().accept(*this);
+    stop_chrono();
+}
 
-        for (const auto & out : macrodef.getOut())
+void GlobalsCollector::visit(ast::SimpleVar & e)
+{
+    if (!e.getParent()->isFieldExp() || static_cast<ast::FieldExp *>(e.getParent())->getTail() != &e)
+    {
+        const symbol::Symbol & sym = e.getSymbol();
+        if (locals.find(sym) == locals.end())
         {
-            if (locals.find(out) == locals.end())
-            {
-                globals.emplace(out);
-            }
+            globals.emplace(sym);
         }
-
-        stop_chrono();
     }
+}
 
-    void GlobalsCollector::visit(ast::SimpleVar & e)
-    {
-       if (!e.getParent()->isFieldExp() || static_cast<ast::FieldExp *>(e.getParent())->getTail() != &e)
-       {
-           const symbol::Symbol & sym = e.getSymbol();
-           if (locals.find(sym) == locals.end())
-           {
-               globals.emplace(sym);
-           }
-       }
-    }
+void GlobalsCollector::visit(ast::DollarVar & e)
+{
+    // nothing to do
+}
 
-    void GlobalsCollector::visit(ast::DollarVar & e)
-    {
-        // nothing to do
-    }
+void GlobalsCollector::visit(ast::ColonVar & e)
+{
+    // nothing to do
+}
 
-    void GlobalsCollector::visit(ast::ColonVar & e)
+void GlobalsCollector::visit(ast::ArrayListVar & e)
+{
+    for (auto arg : e.getVars())
     {
-        // nothing to do
+        arg->accept(*this);
     }
+}
 
-    void GlobalsCollector::visit(ast::ArrayListVar & e)
-    {
-        for (auto arg : e.getVars())
-        {
-            arg->accept(*this);
-        }
-    }
+void GlobalsCollector::visit(ast::DoubleExp & e)
+{
+}
 
-    void GlobalsCollector::visit(ast::DoubleExp & e)
-    {
-    }
+void GlobalsCollector::visit(ast::BoolExp & e)
+{
+}
 
-    void GlobalsCollector::visit(ast::BoolExp & e)
-    {
-    }
+void GlobalsCollector::visit(ast::StringExp & e)
+{
+}
 
-    void GlobalsCollector::visit(ast::StringExp & e)
-    {
-    }
+void GlobalsCollector::visit(ast::CommentExp & e)
+{
+    // ignored
+}
 
-    void GlobalsCollector::visit(ast::CommentExp & e)
-    {
-        // ignored
-    }
+void GlobalsCollector::visit(ast::NilExp & e)
+{
+    // nothing to do
+}
 
-    void GlobalsCollector::visit(ast::NilExp & e)
+void GlobalsCollector::visit(ast::CallExp & e)
+{
+    for (auto arg : e.getArgs())
     {
-        // nothing to do
+        arg->accept(*this);
     }
+    e.getName().accept(*this);
+}
 
-    void GlobalsCollector::visit(ast::CallExp & e)
+void GlobalsCollector::visit(ast::CellCallExp & e)
+{
+    for (auto arg : e.getArgs())
     {
-        for (auto arg : e.getArgs())
-        {
-            arg->accept(*this);
-        }
-        e.getName().accept(*this);
+        arg->accept(*this);
     }
+    e.getName().accept(*this);
+}
 
-    void GlobalsCollector::visit(ast::CellCallExp & e)
-    {
-        for (auto arg : e.getArgs())
-        {
-            arg->accept(*this);
-        }
-        e.getName().accept(*this);
-    }
+void GlobalsCollector::visit(ast::OpExp & e)
+{
+    e.getLeft().accept(*this);
+    e.getRight().accept(*this);
+}
 
-    void GlobalsCollector::visit(ast::OpExp & e)
-    {
-        e.getLeft().accept(*this);
-        e.getRight().accept(*this);
-    }
+void GlobalsCollector::visit(ast::LogicalOpExp & e)
+{
+    e.getLeft().accept(*this);
+    e.getRight().accept(*this);
+}
 
-    void GlobalsCollector::visit(ast::LogicalOpExp & e)
+void GlobalsCollector::visit(ast::AssignExp & e)
+{
+    if (e.getLeftExp().isSimpleVar())
     {
-        e.getLeft().accept(*this);
-        e.getRight().accept(*this);
+        // A = ...
+        const symbol::Symbol & Lsym = static_cast<ast::SimpleVar &>(e.getLeftExp()).getSymbol();
+        locals.emplace(Lsym);
     }
-
-    void GlobalsCollector::visit(ast::AssignExp & e)
+    else if (e.getLeftExp().isCallExp())
     {
-        if (e.getLeftExp().isSimpleVar())
+        // A(...) = ...
+        ast::CallExp & ce = static_cast<ast::CallExp &>(e.getLeftExp());
+        if (ce.getName().isSimpleVar())
         {
-            const symbol::Symbol & Lsym = static_cast<ast::SimpleVar &>(e.getLeftExp()).getSymbol();
+            const symbol::Symbol & Lsym = static_cast<ast::SimpleVar &>(ce.getName()).getSymbol();
             locals.emplace(Lsym);
         }
-        else if (e.getLeftExp().isCallExp())
+        for (auto arg : ce.getArgs())
         {
-            ast::CallExp & ce = static_cast<ast::CallExp &>(e.getLeftExp());
-            if (ce.getName().isSimpleVar())
-            {
-                const symbol::Symbol & Lsym = static_cast<ast::SimpleVar &>(ce.getName()).getSymbol();
-                locals.emplace(Lsym);
-            }
-            for (auto arg : ce.getArgs())
-            {
-                arg->accept(*this);
-            }
+            arg->accept(*this);
         }
-        else if (e.getLeftExp().isAssignListExp())
+    }
+    else if (e.getLeftExp().isAssignListExp())
+    {
+        // [A, ...] =
+        ast::AssignListExp & ale = static_cast<ast::AssignListExp &>(e.getLeftExp());
+        for (const auto re : ale.getExps())
         {
-            ast::AssignListExp & ale = static_cast<ast::AssignListExp &>(e.getLeftExp());
-            for (const auto re : ale.getExps())
+            if (re->isSimpleVar())
             {
-                if (re->isSimpleVar())
-                {
-                    const symbol::Symbol & Lsym = static_cast<const ast::SimpleVar *>(re)->getSymbol();
-                    locals.emplace(Lsym);
-                }
+                const symbol::Symbol & Lsym = static_cast<const ast::SimpleVar *>(re)->getSymbol();
+                locals.emplace(Lsym);
             }
         }
-        else
-        {
-            e.getLeftExp().accept(*this);
-        }
-        e.getRightExp().accept(*this);
     }
-
-    void GlobalsCollector::visit(ast::IfExp & e)
+    else
     {
-        e.getTest().accept(*this);
-        e.getThen().accept(*this);
-        if (e.hasElse())
-        {
-            e.getElse().accept(*this);
-        }
+        e.getLeftExp().accept(*this);
     }
+    e.getRightExp().accept(*this);
+}
 
-    void GlobalsCollector::visit(ast::WhileExp & e)
+void GlobalsCollector::visit(ast::IfExp & e)
+{
+    e.getTest().accept(*this);
+    e.getThen().accept(*this);
+    if (e.hasElse())
     {
-        e.getTest().accept(*this);
-        e.getBody().accept(*this);
+        e.getElse().accept(*this);
     }
+}
 
-    void GlobalsCollector::visit(ast::ForExp & e)
-    {
-        e.getVardec().accept(*this);
-        e.getBody().accept(*this);
-    }
+void GlobalsCollector::visit(ast::WhileExp & e)
+{
+    e.getTest().accept(*this);
+    e.getBody().accept(*this);
+}
 
-    void GlobalsCollector::visit(ast::BreakExp & e)
-    {
-        // nothing to do
-    }
+void GlobalsCollector::visit(ast::ForExp & e)
+{
+    e.getVardec().accept(*this);
+    e.getBody().accept(*this);
+}
 
-    void GlobalsCollector::visit(ast::ContinueExp & e)
-    {
-        // nothing to do
-    }
+void GlobalsCollector::visit(ast::BreakExp & e)
+{
+    // nothing to do
+}
 
-    void GlobalsCollector::visit(ast::TryCatchExp & e)
-    {
-        e.getTry().accept(*this);
-        e.getCatch().accept(*this);
-    }
+void GlobalsCollector::visit(ast::ContinueExp & e)
+{
+    // nothing to do
+}
 
-    void GlobalsCollector::visit(ast::SelectExp & e)
-    {
-        e.getSelect()->accept(*this);
-        for (auto _e : e.getCases())
-        {
-            _e->accept(*this);
-        }
-        if (ast::Exp * def = e.getDefaultCase())
-        {
-            def->accept(*this);
-        }
-    }
+void GlobalsCollector::visit(ast::TryCatchExp & e)
+{
+    e.getTry().accept(*this);
+    e.getCatch().accept(*this);
+}
 
-    void GlobalsCollector::visit(ast::CaseExp & e)
+void GlobalsCollector::visit(ast::SelectExp & e)
+{
+    e.getSelect()->accept(*this);
+    for (auto _e : e.getCases())
     {
-        e.getTest()->accept(*this);
-        e.getBody()->accept(*this);
+        _e->accept(*this);
     }
-
-    void GlobalsCollector::visit(ast::ReturnExp & e)
+    if (ast::Exp * def = e.getDefaultCase())
     {
-        // Bug with return;
-        //e.exp_get().accept(*this);
+        def->accept(*this);
     }
+}
 
-    void GlobalsCollector::visit(ast::FieldExp & e)
-    {
-        e.getHead()->accept(*this);
-        e.getTail()->accept(*this);
-    }
+void GlobalsCollector::visit(ast::CaseExp & e)
+{
+    e.getTest()->accept(*this);
+    e.getBody()->accept(*this);
+}
 
-    void GlobalsCollector::visit(ast::NotExp & e)
-    {
-        e.getExp().accept(*this);
-    }
+void GlobalsCollector::visit(ast::ReturnExp & e)
+{
+    // Bug with return;
+    //e.exp_get().accept(*this);
+}
 
-    void GlobalsCollector::visit(ast::TransposeExp & e)
-    {
-        e.getExp().accept(*this);
-    }
+void GlobalsCollector::visit(ast::FieldExp & e)
+{
+    e.getHead()->accept(*this);
+    e.getTail()->accept(*this);
+}
 
-    void GlobalsCollector::visit(ast::MatrixExp & e)
-    {
-        for (auto mle : e.getLines())
-        {
-            mle->accept(*this);
-        }
-    }
+void GlobalsCollector::visit(ast::NotExp & e)
+{
+    e.getExp().accept(*this);
+}
 
-    void GlobalsCollector::visit(ast::MatrixLineExp & e)
-    {
-        for (auto _e : e.getColumns())
-        {
-            _e->accept(*this);
-        }
-    }
+void GlobalsCollector::visit(ast::TransposeExp & e)
+{
+    e.getExp().accept(*this);
+}
 
-    void GlobalsCollector::visit(ast::CellExp & e)
+void GlobalsCollector::visit(ast::MatrixExp & e)
+{
+    for (auto mle : e.getLines())
     {
-        for (auto mle : e.getLines())
-        {
-            mle->accept(*this);
-        }
+        mle->accept(*this);
     }
+}
 
-    void GlobalsCollector::visit(ast::SeqExp & e)
+void GlobalsCollector::visit(ast::MatrixLineExp & e)
+{
+    for (auto _e : e.getColumns())
     {
-        for (auto _e : e.getExps())
-        {
-            _e->accept(*this);
-        }
+        _e->accept(*this);
     }
+}
 
-    void GlobalsCollector::visit(ast::ArrayListExp & e)
+void GlobalsCollector::visit(ast::CellExp & e)
+{
+    for (auto mle : e.getLines())
     {
-        for (auto _e : e.getExps())
-        {
-            _e->accept(*this);
-        }
+        mle->accept(*this);
     }
+}
 
-    void GlobalsCollector::visit(ast::AssignListExp & e)
+void GlobalsCollector::visit(ast::SeqExp & e)
+{
+    for (auto _e : e.getExps())
     {
+        _e->accept(*this);
     }
+}
 
-    void GlobalsCollector::visit(ast::VarDec & e)
+void GlobalsCollector::visit(ast::ArrayListExp & e)
+{
+    for (auto _e : e.getExps())
     {
-        locals.emplace(e.getSymbol());
-        e.getInit().accept(*this);
+        _e->accept(*this);
     }
+}
 
-    void GlobalsCollector::visit(ast::FunctionDec & e)
-    {
-        locals.emplace(e.getSymbol());
-        DeclaredMacroDef dmd(&e);
-        GlobalsCollector gc(dmd);
+void GlobalsCollector::visit(ast::AssignListExp & e)
+{
+}
+
+void GlobalsCollector::visit(ast::VarDec & e)
+{
+    locals.emplace(e.getSymbol());
+    e.getInit().accept(*this);
+}
 
-        for (const auto global : gc.globals)
+void GlobalsCollector::visit(ast::FunctionDec & e)
+{
+    locals.emplace(e.getSymbol());
+    DeclaredMacroDef dmd(&e);
+    GlobalsCollector gc(dmd);
+
+    for (const auto global : gc.globals)
+    {
+        if (locals.find(global) == locals.end())
         {
-            if (locals.find(global) == locals.end())
-            {
-                globals.emplace(global);
-            }
+            globals.emplace(global);
         }
     }
+}
 
-    void GlobalsCollector::visit(ast::ListExp & e)
-    {
-        e.getStart().accept(*this);
-        e.getStep().accept(*this);
-        e.getEnd().accept(*this);
-    }
+void GlobalsCollector::visit(ast::ListExp & e)
+{
+    e.getStart().accept(*this);
+    e.getStep().accept(*this);
+    e.getEnd().accept(*this);
+}
 
-    void GlobalsCollector::visit(ast::OptimizedExp & e)
-    {
-    }
+void GlobalsCollector::visit(ast::OptimizedExp & e)
+{
+}
 
-    void GlobalsCollector::visit(ast::MemfillExp & e)
-    {
-    }
+void GlobalsCollector::visit(ast::MemfillExp & e)
+{
+}
 
-    void GlobalsCollector::visit(ast::DAXPYExp & e)
-       {
-       }
-    
-    void GlobalsCollector::visit(ast::IntSelectExp & e)
-       {
-           visit(static_cast<ast::SelectExp &>(e));
-       }
-    
-    void GlobalsCollector::visit(ast::StringSelectExp & e)
-       {
-           visit(static_cast<ast::SelectExp &>(e));
-       }
+void GlobalsCollector::visit(ast::DAXPYExp & e)
+{
+}
+
+void GlobalsCollector::visit(ast::IntSelectExp & e)
+{
+    visit(static_cast<ast::SelectExp &>(e));
+}
+
+void GlobalsCollector::visit(ast::StringSelectExp & e)
+{
+    visit(static_cast<ast::SelectExp &>(e));
+}
 
 } // namespace analysis
index bd29b88..2f34287 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include "data/LoopBlock.hxx"
+#include "data/LoopAnalyzer.hxx"
 
 namespace analysis
 {
@@ -20,11 +21,11 @@ bool LoopBlock::requiresAnotherTrip()
     {
         for (auto & p : symMap)
         {
-            std::map<symbol::Symbol, Info>::iterator it;
+            tools::SymbolMap<Info>::iterator it;
             Block * block = getParent()->getDefBlock(p.first, it, false);
             if (block)
             {
-                Info & info = it->second;
+                const Info & info = it->second;
                 if (info.type != p.second.type || !info.data->same(p.second.data))
                 {
                     return true;
@@ -32,11 +33,27 @@ bool LoopBlock::requiresAnotherTrip()
             }
         }
     }
+    else
+    {
+        tools::SymbolMap<Info> & map = getParent()->getFirstBlock()->getMap();
+        for (auto & p : symMap)
+        {
+            auto i = map.find(p.first);
+            if (i != map.end())
+            {
+                Info & info = i->second;
+                if (info.type != p.second.type)
+                {
+                    return true;
+                }
+            }
+        }
+    }
 
     return false;
 }
 
-    Block * LoopBlock::getDefBlock(const symbol::Symbol & sym, std::map<symbol::Symbol, Info>::iterator & it, const bool global)
+Block * LoopBlock::getDefBlock(const symbol::Symbol & sym, tools::SymbolMap<Info>::iterator & it, const bool global)
 {
     if (first)
     {
@@ -75,14 +92,76 @@ Block * LoopBlockHead::addBlock(const unsigned int id, BlockKind kind, ast::Exp
     return b;
 }
 
+void LoopBlock::clone(const symbol::Symbol & sym, ast::Exp * exp)
+{
+    clonedSym.emplace(exp, sym);
+}
+
 void LoopBlockHead::finalize()
 {
-    if (false && blocks.size() == 2)
+    if (blocks.size() == 2)
     {
-        // TODO
+        LoopBlock * fb = static_cast<LoopBlock *>(getFirstBlock());
+        LoopBlock * sb = static_cast<LoopBlock *>(getSecondBlock());
+        std::unordered_map<ast::Exp *, symbol::Symbol> onlyInFirst;
+        std::unordered_map<ast::Exp *, symbol::Symbol> inBoth;
+
+        for (const auto & p : fb->clonedSym)
+        {
+            const auto i = sb->clonedSym.find(p.first);
+            if (i == sb->clonedSym.end())
+            {
+                // In first and not in second
+                onlyInFirst.emplace(p);
+            }
+            else
+            {
+                // In first and in second
+                inBoth.emplace(p);
+                sb->clonedSym.erase(i);
+            }
+        }
+
+        // Since we removed common elements from sb->clonedSym
+        // the remainder is the elements which are only in second
+
+        // Now we merge
+        // i) clone is only in the first loop so we can move it in the loop header
+        if (parent && !onlyInFirst.empty())
+        {
+            for (auto & p : onlyInFirst)
+            {
+                parent->clone(p.second, exp);
+            }
+        }
+
+        // ii) clone is in first and in second so we clone the data at each iteration
+        // iii) clone is only in second so we clone the daat at each iteration except for the first one
+        //      => for now, we clone at each iteration (TODO: improve that in removing clone at the first iteration)
+        for (auto & p : inBoth)
+        {
+            p.first->getDecorator().addClone(p.second);
+        }
+
+        for (auto & p : sb->clonedSym)
+        {
+            p.first->getDecorator().addClone(p.second);
+        }
+
+        pullup(symMap);
+        pullup(getSecondBlock()->getMap());
     }
     else
     {
+        LoopBlock * fb = static_cast<LoopBlock *>(getFirstBlock());
+        if (parent && !fb->clonedSym.empty())
+        {
+            for (auto & p : fb->clonedSym)
+            {
+                parent->clone(p.second, p.first);
+            }
+        }
+
         pullup(symMap);
         pullup(getFirstBlock()->getMap());
     }
index 6f923f0..b2f3005 100644 (file)
 
 namespace analysis
 {
-    const bool PolymorphicMacroCache::getOutTypes(AnalysisVisitor & visitor, MacroDef * macrodef, std::vector<TIType> & in, std::vector<TIType> & out)
-    {
-
-        // TODO: handle varargin
-        if (in.size() > macrodef->getRhs())
-        {
-            return false;
-        }
+const bool PolymorphicMacroCache::getOutTypes(AnalysisVisitor & visitor, MacroDef * macrodef, std::vector<TIType> & in, std::vector<TIType> & out)
+{
 
-        std::vector<TIType> completeIn;
-        if (!PolymorphicMacroCache::getCompleteIn(*macrodef, visitor, in, completeIn))
-        {
-            return false;
-        }
+    // TODO: handle varargin
+    if (in.size() > macrodef->getRhs())
+    {
+        return false;
+    }
 
-        MacroSignature signature(*macrodef, out.size(), completeIn);
-        MacroSignMap::iterator i = signatures.find(signature);
-        if (i == signatures.end())
-        {
-            i = signatures.emplace(signature, 0).first;
-        }
+    std::vector<TIType> completeIn;
+    if (!PolymorphicMacroCache::getCompleteIn(*macrodef, visitor, in, completeIn))
+    {
+        return false;
+    }
 
-        CompleteMacroSignature & cms = i->second;
-        std::vector<GVN::Value *> values;
-        std::vector<const MultivariatePolynomial *> polys;
-        for (auto & t : completeIn)
-        {
-            if (t.isscalar())
-            {
-                GVN::Value * v = t.rows.getValue();
-                values.emplace_back(v);
-                polys.emplace_back(v->poly);
-            }
-            else
-            {
-                GVN::Value * v = t.rows.getValue();
-                values.emplace_back(v);
-                polys.emplace_back(v->poly);
-                v = t.cols.getValue();
-                values.emplace_back(v);
-                polys.emplace_back(v->poly);
-            }
-        }
+    MacroSignature signature(*macrodef, out.size(), completeIn);
+    MacroSignMap::iterator i = signatures.find(signature);
+    if (i == signatures.end())
+    {
+        i = signatures.emplace(signature, 0).first;
+    }
 
-        const MacroOut * mout = cms.getOutTypes(visitor, signature, macrodef, visitor.getDM(), in.size(), completeIn, values);
-        if (mout)
+    CompleteMacroSignature & cms = i->second;
+    std::vector<GVN::Value *> values;
+    std::vector<const MultivariatePolynomial *> polys;
+    for (auto & t : completeIn)
+    {
+        if (t.isscalar())
         {
-            std::vector<TIType>::iterator i = out.begin();
-            for (const auto & t : mout->tuple.types)
-            {
-                *i = t;
-                GVN::Value * Rv = getValue(t.rows.getValue(), visitor, polys, mout->maxVarId);
-                GVN::Value * Cv = getValue(t.cols.getValue(), visitor, polys, mout->maxVarId);
-                i->rows.setValue(Rv);
-                i->cols.setValue(Cv);
-                i->invalidScalar();
-                ++i;
-            }
-
-            //out.assign(mout->tuple.types.begin(), mout->tuple.types.end());
-            return true;
+            GVN::Value * v = t.rows.getValue();
+            values.emplace_back(v);
+            polys.emplace_back(v->poly);
         }
         else
         {
-            return false;
+            GVN::Value * v = t.rows.getValue();
+            values.emplace_back(v);
+            polys.emplace_back(v->poly);
+            v = t.cols.getValue();
+            values.emplace_back(v);
+            polys.emplace_back(v->poly);
         }
     }
 
-    bool PolymorphicMacroCache::getCompleteIn(MacroDef & macrodef, AnalysisVisitor & visitor, const std::vector<TIType> & in, std::vector<TIType> & completeIn)
+    const MacroOut * mout = cms.getOutTypes(visitor, signature, macrodef, visitor.getDM(), in.size(), completeIn, values);
+    if (mout)
     {
-        for (const auto & ty : in)
+        std::vector<TIType>::iterator i = out.begin();
+        for (const auto & t : mout->tuple.types)
         {
-            if (ty.type == TIType::UNKNOWN)
-            {
-                return false;
-            }
+            *i = t;
+            GVN::Value * Rv = getValue(t.rows.getValue(), visitor, polys, mout->maxVarId);
+            GVN::Value * Cv = getValue(t.cols.getValue(), visitor, polys, mout->maxVarId);
+            i->rows.setValue(Rv);
+            i->cols.setValue(Cv);
+            i->invalidScalar();
+            ++i;
         }
 
-        const std::set<symbol::Symbol> & globals = macrodef.getGlobals();
-        completeIn.reserve(in.size() + globals.size());
-        for (const auto & ty : in)
+        //out.assign(mout->tuple.types.begin(), mout->tuple.types.end());
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+bool PolymorphicMacroCache::getCompleteIn(MacroDef & macrodef, AnalysisVisitor & visitor, const std::vector<TIType> & in, std::vector<TIType> & completeIn)
+{
+    for (const auto & ty : in)
+    {
+        if (ty.type == TIType::UNKNOWN)
         {
-            completeIn.emplace_back(ty);
+            return false;
         }
+    }
+
+    const tools::SymbolOrdSet & globals = macrodef.getGlobals();
+    completeIn.reserve(in.size() + globals.size());
+    for (const auto & ty : in)
+    {
+        completeIn.emplace_back(ty);
+    }
 
-        const std::vector<symbol::Symbol> & declaredIn = macrodef.getIn();
-        const unsigned int size = declaredIn.size();
-        DataManager & dm = visitor.getDM();
+    const std::vector<symbol::Symbol> & declaredIn = macrodef.getIn();
+    const unsigned int size = declaredIn.size();
+    DataManager & dm = visitor.getDM();
 
-        if (in.size() < size)
+    if (in.size() < size)
+    {
+        // we have less rhs than declared rhs:
+        // function foo(x,y,z)...endfunction
+        // called with foo(x) so y and z are globals
+        for (unsigned int i = in.size(); i < size; ++i)
         {
-            // we have less rhs than declared rhs:
-            // function foo(x,y,z)...endfunction
-            // called with foo(x) so y and z are globals
-            for (unsigned int i = in.size(); i < size; ++i)
-            {
-                completeIn.emplace_back(dm.getType(declaredIn[i]));
-            }
+            completeIn.emplace_back(dm.getType(declaredIn[i]));
         }
+    }
 
-        for (const auto & sym : globals)
+    for (const auto & sym : globals)
+    {
+        TIType ty = dm.getType(sym, /* global */ true);
+        completeIn.emplace_back(ty);
+        if (ty.type == TIType::UNKNOWN)
         {
-            TIType ty = dm.getType(sym, /* global */ true);
-            completeIn.emplace_back(ty);
-            if (ty.type == TIType::UNKNOWN)
-            {
-                return false;
-            }
+            return false;
         }
-
-        return true;
     }
 
+    return true;
+}
+
 
-    GVN::Value * PolymorphicMacroCache::getValue(const GVN::Value * value, AnalysisVisitor & visitor, const std::vector<const MultivariatePolynomial *> & polys, const int maxVarId) const
+GVN::Value * PolymorphicMacroCache::getValue(const GVN::Value * value, AnalysisVisitor & visitor, const std::vector<const MultivariatePolynomial *> & polys, const int maxVarId) const
+{
+    if (value->poly->containsVarsGEq(maxVarId + 1))
     {
-        if (value->poly->containsVarsGEq(maxVarId + 1))
+        // we translate variables with an id which could conflict with ids in the poly
+        MultivariatePolynomial mp1 = value->poly->translateVariables(visitor.getGVN().getCurrentValue() + 1, maxVarId + 1);
+        MultivariatePolynomial mp2 = mp1.eval(polys);
+        if (mp2.containsVarsGEq(visitor.getGVN().getCurrentValue() + 1))
         {
-            // we translate variables with an id which could conflict with ids in the poly
-            MultivariatePolynomial mp1 = value->poly->translateVariables(visitor.getGVN().getCurrentValue() + 1, maxVarId + 1);
-            MultivariatePolynomial mp2 = mp1.eval(polys);
-            if (mp2.containsVarsGEq(visitor.getGVN().getCurrentValue() + 1))
-            {
-                // after evaluation, we have always values coming from the function block GVN
-                return visitor.getGVN().getValue();
-            }
-            else
-            {
-                return visitor.getGVN().getValue(mp2);
-            }
+            // after evaluation, we have always values coming from the function block GVN
+            return visitor.getGVN().getValue();
         }
         else
         {
-            // the out poly is only an expression of the in values
-            MultivariatePolynomial mp = value->poly->eval(polys);
-            return visitor.getGVN().getValue(mp);
+            return visitor.getGVN().getValue(mp2);
         }
     }
+    else
+    {
+        // the out poly is only an expression of the in values
+        MultivariatePolynomial mp = value->poly->eval(polys);
+        return visitor.getGVN().getValue(mp);
+    }
+}
 
 } // namespace analysis
index 0afcba1..7e6cb22 100644 (file)
@@ -27,7 +27,10 @@ void AnalysisVisitor::visit(ast::AssignExp & e)
         {
             // We have A = B (so the data associated to b is shared with a)
             const symbol::Symbol & symR = static_cast<ast::SimpleVar &>(e.getRightExp()).getSymbol();
-            getDM().share(sym, symR, getSymInfo(symR).getType(), &e);
+            const TIType & Rtype = getSymInfo(symR).getType();
+            getDM().share(sym, symR, Rtype, &e);
+            static_cast<ast::SimpleVar &>(e.getRightExp()).getDecorator().setResult(Rtype);
+            static_cast<ast::SimpleVar &>(e.getLeftExp()).getDecorator().setResult(Rtype);
         }
         else
         {
@@ -57,6 +60,7 @@ void AnalysisVisitor::visit(ast::AssignExp & e)
             var.getDecorator().res = RR;
             Info & info = getDM().define(sym, RR.getType(), RR.isAnInt(), &e);
             info.getConstant() = RR.getConstant();
+            e.getDecorator().safe = true;
             getDM().releaseTmp(RR.getTempId());
         }
     }
@@ -69,7 +73,7 @@ void AnalysisVisitor::visit(ast::AssignExp & e)
             e.getRightExp().accept(*this);
             Result & RR = e.getRightExp().getDecorator().getResult();
             ce.getDecorator().res = RR;
-            Info & info = getDM().write(symL, RR.getType(), &e);
+            Info & info = getDM().write(symL, RR.getType(), &ce.getName());
             ce.getName().getDecorator().setResult(info.type);
             if (analyzeIndices(info.type, ce))
             {
index 1b68f7c..86595bf 100644 (file)
 namespace analysis
 {
 
-    void AnalysisVisitor::visit(ast::IfExp & e)
-    {
-        logger.log(L"IfExp", e.getLocation());
-        ast::Exp * shortcutExp = nullptr;
+void AnalysisVisitor::visit(ast::IfExp & e)
+{
+    logger.log(L"IfExp", e.getLocation());
+    ast::Exp * shortcutExp = nullptr;
 
-        // we apply the ConstantVisitor
-        e.getTest().accept(cv);
-        ast::Exp & test = e.getTest();
+    // we apply the ConstantVisitor
+    e.getTest().accept(cv);
+    ast::Exp & test = e.getTest();
 
-        if (cv.getResult() && test.isConstExp())
+    if (cv.getResult() && test.isConstExp())
+    {
+        e.accept(cv);
+        // we have a constant !
+        ast::ConstExp & ce = static_cast<ast::ConstExp &>(test);
+        types::InternalType * pIT = ce.getConstant();
+        if (!pIT)
         {
-            e.accept(cv);
-            // we have a constant !
-            ast::ConstExp & ce = static_cast<ast::ConstExp &>(test);
-            types::InternalType * pIT = ce.getConstant();
-            if (!pIT)
+            test.accept(cv.getExec());
+            pIT = ce.getConstant();
+        }
+        if (pIT)
+        {
+            const bool result = pIT->isTrue();
+            if (result)
             {
-                test.accept(cv.getExec());
-                pIT = ce.getConstant();
+                shortcutExp = &e.getThen();
+                e.getExps()[1] = nullptr;
             }
-            if (pIT)
+            else
             {
-                const bool result = pIT->isTrue();
-                if (result)
+                shortcutExp = &e.getElse();
+                e.getExps()[2] = nullptr;
+            }
+        }
+    }
+    else
+    {
+        ast::Exp * val = nullptr;
+        bool isEq;
+        if (test.isOpExp())
+        {
+            ast::OpExp & oe = static_cast<ast::OpExp &>(test);
+            isEq = oe.getOper() == ast::OpExp::eq;
+            if (isEq || oe.getOper() == ast::OpExp::ne)
+            {
+                if (oe.getLeft().isDoubleExp())
                 {
-                    shortcutExp = &e.getThen();
-                    e.getExps()[1] = nullptr;
+                    ast::DoubleExp & de = static_cast<ast::DoubleExp &>(oe.getLeft());
+                    if (types::InternalType * pIT = de.getConstant())
+                    {
+                        if (pIT->isDouble())
+                        {
+                            types::Double * pDbl = static_cast<types::Double *>(pIT);
+                            if (pDbl->isEmpty())
+                            {
+                                val = &oe.getRight();
+                            }
+                        }
+                    }
                 }
-                else
+                else if (oe.getRight().isDoubleExp())
                 {
-                    shortcutExp = &e.getElse();
-                    e.getExps()[2] = nullptr;
+                    ast::DoubleExp & de = static_cast<ast::DoubleExp &>(oe.getRight());
+                    if (types::InternalType * pIT = de.getConstant())
+                    {
+                        if (pIT->isDouble())
+                        {
+                            types::Double * pDbl = static_cast<types::Double *>(pIT);
+                            if (pDbl->isEmpty())
+                            {
+                                val = &oe.getLeft();
+                            }
+                        }
+                    }
                 }
             }
         }
-       else
-       {
-           ast::Exp * val = nullptr;
-           bool isEq;
-           if (test.isOpExp())
-           {
-               ast::OpExp & oe = static_cast<ast::OpExp &>(test);
-               isEq = oe.getOper() == ast::OpExp::eq;
-               if (isEq || oe.getOper() == ast::OpExp::ne)
-               {
-                   if (oe.getLeft().isDoubleExp())
-                   {
-                       ast::DoubleExp & de = static_cast<ast::DoubleExp &>(oe.getLeft());
-                       if (types::InternalType * pIT = de.getConstant())
-                       {
-                           if (pIT->isDouble())
-                           {
-                               types::Double * pDbl = static_cast<types::Double *>(pIT);
-                               if (pDbl->isEmpty())
-                               {
-                                   val = &oe.getRight();
-                               }
-                           }
-                       }
-                   }
-                   else if (oe.getRight().isDoubleExp())
-                   {
-                       ast::DoubleExp & de = static_cast<ast::DoubleExp &>(oe.getRight());
-                       if (types::InternalType * pIT = de.getConstant())
-                       {
-                           if (pIT->isDouble())
-                           {
-                               types::Double * pDbl = static_cast<types::Double *>(pIT);
-                               if (pDbl->isEmpty())
-                               {
-                                   val = &oe.getLeft();
-                               }
-                           }
-                       }
-                   } 
-               }
-           }
-           else
-           {
-               ast::CallExp * ce = nullptr;
-               if (test.isNotExp())
-               {
-                   ast::NotExp & ne = static_cast<ast::NotExp &>(test);
-                   if (ne.getExp().isCallExp())
-                   {
-                       ce = &static_cast<ast::CallExp &>(ne.getExp());
-                       isEq = false;
-                   }
-               }
-               else if (test.isCallExp())
-               {
-                   ce = &static_cast<ast::CallExp &>(test);
-                   isEq = true;
-               }
-
-               if (ce && ce->getName().isSimpleVar())
-               {
-                   ast::SimpleVar & var = static_cast<ast::SimpleVar &>(ce->getName());
-                   const symbol::Symbol & sym = var.getSymbol();
-                   const std::wstring & name = sym.getName();
-                   if (name == L"isempty" && getCM().checkGlobalConstant(sym))
-                   {
-                       const ast::exps_t args = ce->getArgs();
-                       if (args.size() == 1)
-                       {
-                           val = args.front();
-                       }
-                   }
-               }
-           }
-           
-           if (val)
-           {
-               // test is something like val == [], isempty(val), val ~= [], ~isempty(val)
-               val->accept(*this);
-               Result & res = getResult();
-               TIType & ty = res.getType();
-               if ((ty.ismatrix() && ty.isscalar()) || (getCM().check(ConstraintManager::STRICT_POSITIVE, ty.rows.getValue()) || getCM().check(ConstraintManager::STRICT_POSITIVE, ty.cols.getValue())))
-               {
-                   if (isEq)
-                   {
-                       shortcutExp = &e.getElse();
-                       e.getExps()[2] = nullptr;
-                   }
-                   else
-                   {
-                       shortcutExp = &e.getThen();
-                       e.getExps()[1] = nullptr;
-                   }
-               }
-           }
-       }
-
-        if (shortcutExp)
+        else
         {
-            e.replace(shortcutExp);
-            shortcutExp->accept(*this);
+            ast::CallExp * ce = nullptr;
+            if (test.isNotExp())
+            {
+                ast::NotExp & ne = static_cast<ast::NotExp &>(test);
+                if (ne.getExp().isCallExp())
+                {
+                    ce = &static_cast<ast::CallExp &>(ne.getExp());
+                    isEq = false;
+                }
+            }
+            else if (test.isCallExp())
+            {
+                ce = &static_cast<ast::CallExp &>(test);
+                isEq = true;
+            }
+
+            if (ce && ce->getName().isSimpleVar())
+            {
+                ast::SimpleVar & var = static_cast<ast::SimpleVar &>(ce->getName());
+                const symbol::Symbol & sym = var.getSymbol();
+                const std::wstring & name = sym.getName();
+                if (name == L"isempty" && getCM().checkGlobalConstant(sym))
+                {
+                    const ast::exps_t args = ce->getArgs();
+                    if (args.size() == 1)
+                    {
+                        val = args.front();
+                    }
+                }
+            }
         }
-        else
+
+        if (val)
         {
-            dm.addBlock(Block::EXCLUSIVE, &e);
-            e.getTest().accept(*this);
-            dm.addBlock(Block::NORMAL, &e.getThen());
-            e.getThen().accept(*this);
-            dm.finalizeBlock();
-            dm.addBlock(Block::NORMAL, e.hasElse() ? &e.getElse() : nullptr);
-            if (e.hasElse())
+            // test is something like val == [], isempty(val), val ~= [], ~isempty(val)
+            val->accept(*this);
+            Result & res = getResult();
+            TIType & ty = res.getType();
+            if ((ty.ismatrix() && ty.isscalar()) || (getCM().check(ConstraintManager::STRICT_POSITIVE, ty.rows.getValue()) || getCM().check(ConstraintManager::STRICT_POSITIVE, ty.cols.getValue())))
             {
-                e.getElse().accept(*this);
+                if (isEq)
+                {
+                    shortcutExp = &e.getElse();
+                    e.getExps()[2] = nullptr;
+                }
+                else
+                {
+                    shortcutExp = &e.getThen();
+                    e.getExps()[1] = nullptr;
+                }
             }
-            dm.finalizeBlock();
-            dm.finalizeBlock();
         }
     }
+
+    if (shortcutExp)
+    {
+        e.replace(shortcutExp);
+        shortcutExp->accept(*this);
+    }
+    else
+    {
+        dm.addBlock(Block::EXCLUSIVE, &e);
+        e.getTest().accept(*this);
+        dm.releaseTmp(getResult().getTempId());
+        dm.addBlock(Block::NORMAL, &e.getThen());
+        e.getThen().accept(*this);
+        dm.finalizeBlock();
+        dm.addBlock(Block::NORMAL, e.hasElse() ? &e.getElse() : nullptr);
+        if (e.hasElse())
+        {
+            e.getElse().accept(*this);
+        }
+        dm.finalizeBlock();
+        dm.finalizeBlock();
+    }
+}
 }
index 8dd4f6d..6cb6670 100644 (file)
 namespace analysis
 {
 
-    void AnalysisVisitor::visit(ast::ListExp & e)
+void AnalysisVisitor::visit(ast::ListExp & e)
+{
+    logger.log(L"ListExp", e.getLocation());
+    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();
+
+    if (e.getParent()->isVarDec())
     {
-        logger.log(L"ListExp", e.getLocation());
-        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();
-
-       if (e.getParent()->isVarDec())
-       {
-           GVN::Value * startRange;
-           GVN::Value * endRange;
-           if (Rstart.getConstant().getGVNValue(getGVN(), startRange) && Rend.getConstant().getGVNValue(getGVN(), endRange))
-           {
-               ast::VarDec & vd = *static_cast<ast::VarDec *>(e.getParent());
-               const symbol::Symbol & sym = vd.getSymbol();
-               TIType typ(dm.getGVN(), TIType::DOUBLE);
-               Result & res = e.getDecorator().setResult(Result(typ, -1));
-               res.setRange(SymbolicRange(getGVN(), startRange, endRange));
-               setResult(res);
-               return;
-           }
-       }
-       
-        double start, step, end;
-        if (Rstart.getConstant().getDblValue(start) && Rstep.getConstant().getDblValue(step) && Rend.getConstant().getDblValue(end))
+        ast::VarDec & vd = *static_cast<ast::VarDec *>(e.getParent());
+        const symbol::Symbol & sym = vd.getSymbol();
+        GVN::Value * startRange = nullptr;
+        GVN::Value * endRange = nullptr;
+        if (Rstart.getConstant().getGVNValue(getGVN(), startRange) && Rend.getConstant().getGVNValue(getGVN(), endRange))
         {
-            double out;
-            int type = ForList64::checkList(start, end, step, out);
-
-            switch (type)
+            TIType typ(dm.getGVN(), TIType::DOUBLE);
+            Result & res = e.getDecorator().setResult(Result(typ, -1));
+            res.setRange(SymbolicRange(getGVN(), startRange, endRange));
+            setResult(res);
+            return;
+        }
+        SymbolicRange & rangeStart = Rstart.getRange();
+        if (rangeStart.isValid())
+        {
+            if (endRange || Rend.getConstant().getGVNValue(getGVN(), endRange))
             {
+                // start is an iterator and end is not
+                TIType typ(dm.getGVN(), TIType::DOUBLE);
+                Result & res = e.getDecorator().setResult(Result(typ, -1));
+                res.setRange(SymbolicRange(getGVN(), rangeStart.getStart(), endRange));
+                setResult(res);
+                return;
+            }
+            else
+            {
+                SymbolicRange & rangeEnd = Rend.getRange();
+                if (rangeEnd.isValid())
+                {
+                    TIType typ(dm.getGVN(), TIType::DOUBLE);
+                    Result & res = e.getDecorator().setResult(Result(typ, -1));
+                    res.setRange(SymbolicRange(getGVN(), rangeStart.getStart(), rangeEnd.getEnd()));
+                    setResult(res);
+                    return;
+                }
+            }
+        }
+        // TODO: finish all the cases
+    }
+
+    double start, step, end;
+    if (Rstart.getConstant().getDblValue(start) && Rstep.getConstant().getDblValue(step) && Rend.getConstant().getDblValue(end))
+    {
+        double out;
+        int type = ForList64::checkList(start, end, step, out);
+
+        switch (type)
+        {
             case 0:
                 e.getDecorator().setResult(Result(TIType(dm.getGVN(), TIType::EMPTY), -1));
                 break;
@@ -69,116 +95,116 @@ namespace analysis
             }
             default:
                 break;
-            }
-            e.setValues(start, step, end, out);
-            setResult(e.getDecorator().res);
-
-            return;
         }
+        e.setValues(start, step, end, out);
+        setResult(e.getDecorator().res);
 
-        if (!Rstep.getConstant().getDblValue(step) || (step != -1 && step != 1))
-        {
-            Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
-            setResult(res);
-           return;
-        }
+        return;
+    }
 
-        if (!Rstart.getType().isscalar() || !Rend.getType().isscalar())
-        {
-            Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
-            setResult(res);
-           return;
-        }
+    if (!Rstep.getConstant().getDblValue(step) || (step != -1 && step != 1))
+    {
+        Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
+        setResult(res);
+        return;
+    }
+
+    if (!Rstart.getType().isscalar() || !Rend.getType().isscalar())
+    {
+        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))
+    GVN::Value * gvnStart;
+    if (Rstart.getConstant().getDblValue(start))
+    {
+        if (tools::getIntType(start) == tools::NOTANINT)
         {
-            if (tools::getIntType(start) == tools::NOTANINT)
-            {
-                gvnStart = getGVN().getValue((double)tools::cast<int>(start + step));
-            }
-            else
-            {
-                gvnStart = getGVN().getValue((double)tools::cast<int>(start));
-            }
+            gvnStart = getGVN().getValue((double)tools::cast<int>(start + step));
         }
         else
         {
-            gvnStart = Rstart.getConstant().getGVNValue();
-            if (!gvnStart)
-            {
-                Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
-                setResult(res);
-               return;
-            }
+            gvnStart = getGVN().getValue((double)tools::cast<int>(start));
         }
+    }
+    else
+    {
+        gvnStart = Rstart.getConstant().getGVNValue();
+        if (!gvnStart)
+        {
+            Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
+            setResult(res);
+            return;
+        }
+    }
 
-        GVN::Value * gvnEnd;
+    GVN::Value * gvnEnd;
 
-        if (Rend.getConstant().getDblValue(end))
+    if (Rend.getConstant().getDblValue(end))
+    {
+        if (tools::getIntType(end) == tools::NOTANINT)
         {
-            if (tools::getIntType(end) == tools::NOTANINT)
-            {
-                gvnEnd = getGVN().getValue((double)tools::cast<int>(end - step));
-            }
-            else
-            {
-                gvnEnd = getGVN().getValue((double)tools::cast<int>(end));
-            }
+            gvnEnd = getGVN().getValue((double)tools::cast<int>(end - step));
         }
         else
         {
-            gvnEnd = Rend.getConstant().getGVNValue();
-            if (!gvnEnd)
-            {
-                Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
-                setResult(res);
-               return;
-            }
+            gvnEnd = getGVN().getValue((double)tools::cast<int>(end));
         }
-
-        GVN::Value * ONEValue = getGVN().getValue(1);
-        SymbolicDimension ONE(getGVN(), ONEValue);
-        GVN::Value * v;
-
-        if (gvnStart->value == gvnEnd->value)
+    }
+    else
+    {
+        gvnEnd = Rend.getConstant().getGVNValue();
+        if (!gvnEnd)
         {
-            Result & res = e.getDecorator().setResult(Result(TIType(getGVN(), TIType::DOUBLE, ONE, ONE)));
+            Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
             setResult(res);
-           return;
+            return;
         }
+    }
 
-        if (step == 1)
-        {
-            v = getGVN().getValue(OpValue::Kind::MINUS, *gvnEnd, *gvnStart);
-        }
-        else
-        {
-            v = getGVN().getValue(OpValue::Kind::MINUS, *gvnStart, *gvnEnd);
-        }
-        v = getGVN().getValue(OpValue::Kind::PLUS, *v, *ONEValue);
+    GVN::Value * ONEValue = getGVN().getValue(1);
+    SymbolicDimension ONE(getGVN(), ONEValue);
+    GVN::Value * v;
 
-        if (v->poly->constant < 0 && v->poly->isCoeffNegative(false))
+    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);
+    }
+    else
+    {
+        v = getGVN().getValue(OpValue::Kind::MINUS, *gvnStart, *gvnEnd);
+    }
+    v = getGVN().getValue(OpValue::Kind::PLUS, *v, *ONEValue);
+
+    if (v->poly->constant < 0 && v->poly->isCoeffNegative(false))
+    {
+        TIType type(getGVN(), TIType::EMPTY);
+        e.getDecorator().res = Result(type);
+    }
+    else
+    {
+        bool res = getCM().check(ConstraintManager::POSITIVE, v);
+        if (res)
         {
-            TIType type(getGVN(), TIType::EMPTY);
-            e.getDecorator().res = Result(type);
+            TIType type(getGVN(), TIType::DOUBLE, ONE, SymbolicDimension(getGVN(), v));
+            e.getDecorator().setResult(type);
         }
         else
         {
-            bool res = getCM().check(ConstraintManager::POSITIVE, v);
-            if (res)
-            {
-                TIType type(getGVN(), TIType::DOUBLE, ONE, SymbolicDimension(getGVN(), v));
-                e.getDecorator().setResult(type);
-            }
-            else
-            {
-                Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
-                setResult(res);
-               return;
-            }
+            Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
+            setResult(res);
+            return;
         }
-
-        setResult(e.getDecorator().res);
     }
+
+    setResult(e.getDecorator().res);
+}
 }
index 3de01ad..d175d7e 100644 (file)
 namespace analysis
 {
 
-    void AnalysisVisitor::visit(ast::SelectExp & e)
+void AnalysisVisitor::visit(ast::SelectExp & e)
+{
+    logger.log(L"SelectExp", e.getLocation());
+    e.getSelect()->accept(cv);
+    ast::Exp & select = *e.getSelect();
+    bool found = false;
+    if (cv.getResult() && select.isConstExp())
+    {
+        ast::ConstExp & ce = static_cast<ast::ConstExp &>(select);
+        types::InternalType * pIT = ce.getConstant();
+        if (!pIT)
+        {
+            select.accept(cv.getExec());
+            pIT = ce.getConstant();
+        }
+        if (pIT)
+        {
+            for (ast::exps_t::iterator i = std::next(e.getExps().begin()), end = e.hasDefault() ? std::prev(e.getExps().end()) : e.getExps().end(); i != end; ++i)
+            {
+                ast::CaseExp & casee = *static_cast<ast::CaseExp *>(*i);
+                casee.getTest()->accept(cv);
+                ast::Exp & test = *casee.getTest();
+                if (cv.getResult() && test.isConstExp())
+                {
+                    ast::ConstExp & ce = static_cast<ast::ConstExp &>(test);
+                    types::InternalType * pIT2 = ce.getConstant();
+                    if (!pIT2)
+                    {
+                        test.accept(cv.getExec());
+                        pIT2 = ce.getConstant();
+                    }
+                    if (pIT2)
+                    {
+                        types::InternalType * pIT3 = GenericComparisonEqual(pIT, pIT2);
+                        if (pIT3 && pIT3->isTrue())
+                        {
+                            // We found the good case
+                            e.replace(casee.getBody());
+                            *i = nullptr;
+                            casee.getBody()->accept(*this);
+                            found = true;
+                            break;
+                        }
+                    }
+                }
+            }
+            if (!found && e.hasDefault())
+            {
+                e.getDefaultCase()->accept(*this);
+                e.replace(e.getDefaultCase());
+                *std::prev(e.getExps().end()) = nullptr;
+                found = true;
+            }
+        }
+    }
+
+    if (!found)
     {
-       logger.log(L"SelectExp", e.getLocation());
-        e.getSelect()->accept(cv);
-       ast::Exp & select = *e.getSelect();
-       bool found = false;
-       if (cv.getResult() && select.isConstExp())
-       {
-           ast::ConstExp & ce = static_cast<ast::ConstExp &>(select);
-           types::InternalType * pIT = ce.getConstant();
-           if (!pIT)
-           {
-               select.accept(cv.getExec());
-               pIT = ce.getConstant();
-           }
-           if (pIT)
-           {
-               for (ast::exps_t::iterator i = std::next(e.getExps().begin()), end = e.hasDefault() ? std::prev(e.getExps().end()) : e.getExps().end(); i != end; ++i)
-               {
-                   ast::CaseExp & casee = *static_cast<ast::CaseExp *>(*i);
-                   casee.getTest()->accept(cv);
-                   ast::Exp & test = *casee.getTest();
-                   if (cv.getResult() && test.isConstExp())
-                   {
-                       ast::ConstExp & ce = static_cast<ast::ConstExp &>(test);
-                       types::InternalType * pIT2 = ce.getConstant();
-                       if (!pIT2)
-                       {
-                           test.accept(cv.getExec());
-                           pIT2 = ce.getConstant();
-                       }
-                       if (pIT2)
-                       {
-                           types::InternalType * pIT3 = GenericComparisonEqual(pIT, pIT2);
-                           if (pIT3 && pIT3->isTrue())
-                           {
-                               // We found the good case
-                               e.replace(casee.getBody());
-                               *i = nullptr;
-                               casee.getBody()->accept(*this);
-                               found = true;
-                               break;
-                           }
-                       }
-                   }
-               }
-               if (!found && e.hasDefault())
-               {
-                   e.getDefaultCase()->accept(*this);
-                   e.replace(e.getDefaultCase());
-                   *std::prev(e.getExps().end()) = nullptr;
-                   found = true;
-               }
-           }
-       }
+        dm.addBlock(Block::EXCLUSIVE, &e);
+        e.getSelect()->accept(*this);
+        ast::exps_t cases = e.getCases();
+        for (auto exp : cases)
+        {
+            dm.addBlock(Block::NORMAL, exp);
+            exp->accept(*this);
+            dm.finalizeBlock();
+        }
 
-       if (!found)
-       {
-           dm.addBlock(Block::EXCLUSIVE, &e);
-           e.getSelect()->accept(*this);
-           ast::exps_t cases = e.getCases();
-           for (auto exp : cases)
-           {
-               dm.addBlock(Block::NORMAL, exp);
-               exp->accept(*this);
-               dm.finalizeBlock();
-           }
-           
-           if (e.getDefaultCase())
-           {
-               dm.addBlock(Block::NORMAL, e.getDefaultCase());
-               e.getDefaultCase()->accept(*this);
-               dm.finalizeBlock();
-           }
-           dm.finalizeBlock();
-       }
+        if (e.getDefaultCase())
+        {
+            dm.addBlock(Block::NORMAL, e.getDefaultCase());
+            e.getDefaultCase()->accept(*this);
+            dm.finalizeBlock();
+        }
+        dm.finalizeBlock();
+        analyze(e);
     }
+}
+
+void AnalysisVisitor::analyze(ast::SelectExp & e)
+{
+    enum Kind { INT, STRING, DUNNO };
+    std::vector<int64_t> ints;
+    std::vector<std::wstring> strs;
+    ast::exps_t cases = e.getCases();
+    Kind kind = DUNNO;
+    bool first = true;
 
-    void AnalysisVisitor::analyze(ast::SelectExp & e)
+    for (ast::exps_t::iterator i = cases.begin(), end = cases.end(); i != end; ++i)
     {
-       enum Kind { INT, STRING, DUNNO };
-       std::vector<int64_t> ints;
-       std::vector<std::wstring> strs;
-       ast::exps_t cases = e.getCases();
-       Kind kind = DUNNO;
-       bool first = true;
+        ast::CaseExp & casee = *static_cast<ast::CaseExp *>(*i);
+        ast::Exp & test = *casee.getTest();
+        if (test.isDoubleExp())
+        {
+            ast::DoubleExp & de = static_cast<ast::DoubleExp &>(test);
+            if (first)
+            {
+                kind = INT;
+                first = false;
+            }
+            else if (kind != INT)
+            {
+                kind = DUNNO;
+            }
 
-       for (ast::exps_t::iterator i = cases.begin(), end = cases.end(); i != end; ++i)
-       {
-           ast::CaseExp & casee = *static_cast<ast::CaseExp *>(*i);
-           ast::Exp & test = *casee.getTest();
-           if (test.isDoubleExp())
-           {
-               ast::DoubleExp & de = static_cast<ast::DoubleExp &>(test);
-               if (first)
-               {
-                   kind = INT;
-                   first = false;
-               }
-               else if (kind != INT)
-               {
-                   kind = DUNNO;
-               }
+            int64_t ival;
+            if (kind == INT && tools::asInteger<int64_t>(de.getValue(), ival))
+            {
+                ints.push_back(ival);
+            }
+        }
+        else if (test.isStringExp())
+        {
+            ast::StringExp & se = static_cast<ast::StringExp &>(test);
+            if (first)
+            {
+                kind = STRING;
+                first = false;
+            }
+            else if (kind != STRING)
+            {
+                kind = DUNNO;
+            }
 
-               int64_t ival;
-               if (kind == INT && tools::asInteger<int64_t>(de.getValue(), ival))
-               {
-                   ints.push_back(ival);
-               }
-           }
-           else if (test.isStringExp())
-           {
-               ast::StringExp & se = static_cast<ast::StringExp &>(test);
-               if (first)
-               {
-                   kind = STRING;
-                   first = false;
-               }
-               else if (kind != STRING)
-               {
-                   kind = DUNNO;
-               }
+            if (kind == STRING)
+            {
+                strs.push_back(se.getValue());
+            }
+        }
+    }
 
-               if (kind == STRING)
-               {
-                   strs.push_back(se.getValue());
-               }
-           }
-       }
+    if (kind == INT)
+    {
+        const std::size_t size = ints.size();
+        // Firstly, we check if we have a linear progression
+        if (size > 2)
+        {
+            int64_t min, max;
+            if (ints[0] < ints[1])
+            {
+                min = ints[0];
+                max = ints[1];
+            }
+            else
+            {
+                min = ints[1];
+                max = ints[0];
+            }
+            for (std::size_t i = 2; i < size; ++i)
+            {
+                const int64_t v = ints[i];
+                if (v > max)
+                {
+                    max = v;
+                }
+                else if (v < min)
+                {
+        &nbs