* Bugs 16012, 16014, 16085: fixed regression of insertion in structs 77/20977/10
Stéphane Mottelet [Tue, 14 May 2019 21:02:22 +0000 (23:02 +0200)]
http://bugzilla.scilab.org/show_bug.cgi?id=16014
http://bugzilla.scilab.org/show_bug.cgi?id=16012
http://bugzilla.scilab.org/show_bug.cgi?id=16085
http://bugzilla.scilab.org/show_bug.cgi?id=16087

Change-Id: If3f1b7204698450d731575af46558adf504fcb7f

scilab/CHANGES.md
scilab/modules/ast/src/cpp/ast/visitor_common.cpp
scilab/modules/ast/tests/nonreg_tests/bug_16012.tst [new file with mode: 0644]
scilab/modules/ast/tests/nonreg_tests/bug_16014.tst [new file with mode: 0644]
scilab/modules/ast/tests/nonreg_tests/bug_16085.tst [new file with mode: 0644]
scilab/modules/ast/tests/nonreg_tests/bug_16087.tst [new file with mode: 0644]

index 1585c12..c47513b 100644 (file)
@@ -157,7 +157,11 @@ Bug Fixes
 * [#15995](http://bugzilla.scilab.org/show_bug.cgi?id=15995): patch was missing in surface plot (regression)
 * [#16005](http://bugzilla.scilab.org/show_bug.cgi?id=16005): The `intdec` example was biased and not robust when changing sampling frequencies.
 * [#16007](http://bugzilla.scilab.org/show_bug.cgi?id=16007): Non-integer index in sparse makes Scilab crash.
+* [#16012](http://bugzilla.scilab.org/show_bug.cgi?id=16012): `[struct() struct()]` crashed Scilab.
+* [#16014](http://bugzilla.scilab.org/show_bug.cgi?id=16014): after `x.a=1; x(:)=[]` x.a was an empty list. 
 * [#16021](http://bugzilla.scilab.org/show_bug.cgi?id=16021): `tand([-90 90])` answered [Nan Nan] instead of [-Inf, Inf]. `cotd([-90 90])` answered [Nan Nan] instead of [0 0]. `1 ./cosd([-90 90])` answered [Inf -Inf] instead of [Inf Inf].
 * [#16071](http://bugzilla.scilab.org/show_bug.cgi?id=16071): `prettyprint(complex(1,%nan))` omitted the "+" in `1 + Nani`. It printed positive exponents with a useless "+". For any input nul polynomial, the string result never included the name of the variable. Default input arguments could not be skipped. ExportFormat was uselessly case-sensitive. For tex|latex: for text input, $ \ % & { } ~ and ^ special characters were not protected ; spaces were not protected, all words were concatenated ; for polynomials and rationals, the result string could be extremely long and not easily wrappable. For MathML: "<" was not protected ; <mi></mi> were missing for text input ; <mtable>, </mtable>, <mtr>, </mtr>, <mtd>, <mfenced> and </mfenced> tags were not wrapped and could not be indented. Delimiters: "" was not documented as possible value ; ")" was wrongly documented. Dynamical linear systems were not documented as possible input.
 * [#16072](http://bugzilla.scilab.org/show_bug.cgi?id=16072): `prettyprint()` did not actually support input encoded integers.
 * [#16075](http://bugzilla.scilab.org/show_bug.cgi?id=16075): `prettyprint()` was broken for cells.
+* [#16085](http://bugzilla.scilab.org/show_bug.cgi?id=16085): insertion in an empty struct was broken.
+* [#16087](http://bugzilla.scilab.org/show_bug.cgi?id=16087): Insertion of struct() in a non-empty struct crashed Scilab.
index 3824223..6ba5e0c 100644 (file)
@@ -616,7 +616,7 @@ types::InternalType* callOverload(const ast::Exp& e, const std::wstring& _strTyp
 
     types::InternalType* pFunc = symbol::Context::getInstance()->get(symbol::Symbol(function_name));
     if (pFunc == NULL &&
-        (_source->getShortTypeStr().size() > 8 || _dest && _dest->getShortTypeStr().size() > 8))
+            (_source->getShortTypeStr().size() > 8 || _dest && _dest->getShortTypeStr().size() > 8))
     {
         if (_source->getShortTypeStr().size() > 8)
         {
@@ -756,9 +756,9 @@ bool getFieldsFromExp(ast::Exp* _pExp, std::list<ExpHistory*>& fields)
         // used to manage insertion with list in argument
         // a(list("field", 2)) = 2 as a.field(2)
         if (pCurrentArgs &&  pCurrentArgs->size() > 0 &&
-            (*pCurrentArgs)[0]->isList() &&
-            (*pCurrentArgs)[0]->isTList() == false &&
-            (*pCurrentArgs)[0]->isMList() == false)
+                (*pCurrentArgs)[0]->isList() &&
+                (*pCurrentArgs)[0]->isTList() == false &&
+                (*pCurrentArgs)[0]->isMList() == false)
         {
             bArgList = true;
             pList = (*pCurrentArgs)[0]->getAs<types::List>();
@@ -772,9 +772,9 @@ bool getFieldsFromExp(ast::Exp* _pExp, std::list<ExpHistory*>& fields)
         do
         {
             if (pCurrentArgs &&
-                pCurrentArgs->size() == 1 &&
-                (*pCurrentArgs)[0]->isString() &&
-                (*pCurrentArgs)[0]->getAs<types::String>()->getSize() == 1)
+                    pCurrentArgs->size() == 1 &&
+                    (*pCurrentArgs)[0]->isString() &&
+                    (*pCurrentArgs)[0]->getAs<types::String>()->getSize() == 1)
             {
                 // a("b") => a.b or a(x)("b") => a(x).b
                 ExpHistory * pEHParent = fields.back();
@@ -815,7 +815,8 @@ bool getFieldsFromExp(ast::Exp* _pExp, std::list<ExpHistory*>& fields)
                     pCurrentArgs->push_back(pList->get(iListIncr)->clone());
                 }
             }
-        } while (iListIncr < iListSize);
+        }
+        while (iListIncr < iListSize);
 
         if (bArgList)
         {
@@ -910,11 +911,11 @@ types::InternalType* evaluateFields(const ast::Exp* _pExp, std::list<ExpHistory*
         iterFields++;
 
         workFields.push_back(new ExpHistory(NULL,
-            pFirstField->getExp(),
-            pFirstField->getArgs(),
-            pFirstField->getLevel(),
-            pFirstField->isCellExp(),
-            pITMain));
+                                            pFirstField->getExp(),
+                                            pFirstField->getArgs(),
+                                            pFirstField->getLevel(),
+                                            pFirstField->isCellExp(),
+                                            pITMain));
 
         //*** evaluate fields ***//
         while (iterFields != fields.end())
@@ -1018,11 +1019,11 @@ types::InternalType* evaluateFields(const ast::Exp* _pExp, std::list<ExpHistory*
                         }
 
                         ExpHistory* pEHChield = new ExpHistory(pEH,
-                            (*iterFields)->getExp(),
-                            (*iterFields)->getArgs(),
-                            (*iterFields)->getLevel(),
-                            (*iterFields)->isCellExp(),
-                            pIT);
+                                                               (*iterFields)->getExp(),
+                                                               (*iterFields)->getArgs(),
+                                                               (*iterFields)->getLevel(),
+                                                               (*iterFields)->isCellExp(),
+                                                               pIT);
 
                         pEHChield->setWhereReinsert(0);
                         workFields.push_back(pEHChield);
@@ -2038,7 +2039,7 @@ types::InternalType* insertionCall(const ast::Exp& e, types::typed_list* _pArgs,
             }
             else // insert something in a struct
             {
-                if (_pInsert->isStruct())
+                if (_pInsert->isStruct() && _pInsert->getAs<types::Struct>()->isEmpty() == false)
                 {
                     types::String* pStrFieldsName = pStruct->getFieldNames();
                     types::Struct* pStructInsert = _pInsert->clone()->getAs<types::Struct>();
@@ -2082,6 +2083,14 @@ types::InternalType* insertionCall(const ast::Exp& e, types::typed_list* _pArgs,
 
                         pStrFieldsName->killMe();
                     }
+                    else if (pStrInsertFieldsName)
+                    {
+                        //insertion of non-empty struct in empty struct
+                        for (int i = pStrInsertFieldsName->getSize(); i > 0; i--)
+                        {
+                            pStruct->addFieldFront(pStrInsertFieldsName->get(i - 1));
+                        }
+                    }
 
                     // insert elements in following pArgs
                     pRet = pStruct->insert(_pArgs, pStructInsert);
@@ -2089,16 +2098,29 @@ types::InternalType* insertionCall(const ast::Exp& e, types::typed_list* _pArgs,
 
                     pStructInsert->killMe();
 
-                    // insert fields of pStructInsert in pRet
-                    for (int i = 0; i < pStrInsertFieldsName->getSize(); i++)
+                    // if not an empty struct
+                    if (pStrFieldsName)
                     {
-                        if (pStructRet->exists(pStrInsertFieldsName->get(i)) == false)
+                        // insert fields of pStructInsert in pRet
+                        for (int i = 0; i < pStrInsertFieldsName->getSize(); i++)
                         {
-                            pStructRet->addField(pStrInsertFieldsName->get(i));
+                            if (pStructRet->exists(pStrInsertFieldsName->get(i)) == false)
+                            {
+                                pStructRet->addField(pStrInsertFieldsName->get(i));
+                            }
                         }
-                    }
 
-                    pStrInsertFieldsName->killMe();
+                        pStrInsertFieldsName->killMe();
+                    }
+                }
+                else if (_pInsert->isStruct())
+                {
+                    // insertion of empty struct in a struct
+                    pRet = pStruct;
+                }
+                else if (_pInsert->isDouble() && _pInsert->getAs<types::Double>()->isEmpty())
+                {
+                    pRet = pStruct->remove(_pArgs);
                 }
                 else
                 {
diff --git a/scilab/modules/ast/tests/nonreg_tests/bug_16012.tst b/scilab/modules/ast/tests/nonreg_tests/bug_16012.tst
new file mode 100644 (file)
index 0000000..9f7fab3
--- /dev/null
@@ -0,0 +1,19 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2019 - Stéphane MOTTELET
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+//
+// <-- CLI SHELL MODE -->
+// <-- NO CHECK REF -->
+//
+// <-- Non-regression test for bug 16012 -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/16012
+//
+// <-- Short Description -->
+//  [struct() struct()] crashes scilab
+
+assert_checkequal([struct() struct()],struct())
diff --git a/scilab/modules/ast/tests/nonreg_tests/bug_16014.tst b/scilab/modules/ast/tests/nonreg_tests/bug_16014.tst
new file mode 100644 (file)
index 0000000..5ccee80
--- /dev/null
@@ -0,0 +1,23 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2019 - Stéphane MOTTELET
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+//
+// <-- CLI SHELL MODE -->
+// <-- NO CHECK REF -->
+//
+// <-- Non-regression test for bug 16014 -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/16014
+//
+// <-- Short Description -->
+// After x.a=1; x(:)=[], x.a is an empty list
+
+x.a = 1;
+x(:) = [];
+assert_checktrue(isstruct(x));
+assert_checktrue(isempty(x));
+
diff --git a/scilab/modules/ast/tests/nonreg_tests/bug_16085.tst b/scilab/modules/ast/tests/nonreg_tests/bug_16085.tst
new file mode 100644 (file)
index 0000000..b338fc9
--- /dev/null
@@ -0,0 +1,28 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2019 - Stéphane MOTTELET
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+//
+// <-- CLI SHELL MODE -->
+// <-- NO CHECK REF -->
+//
+// <-- Non-regression test for bug 16085 -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/16085
+//
+// <-- Short Description -->
+// insertion in an empty struct is broken (regression)
+
+x=struct();
+y.b = 1;
+y.c = 2;
+x(:) = y;
+
+assert_checktrue(isstruct(x));
+assert_checkequal(fieldnames(x),["b";"c"])
+assert_checkequal(x.b,1);
+assert_checkequal(x.c,2);
+
diff --git a/scilab/modules/ast/tests/nonreg_tests/bug_16087.tst b/scilab/modules/ast/tests/nonreg_tests/bug_16087.tst
new file mode 100644 (file)
index 0000000..2c48069
--- /dev/null
@@ -0,0 +1,25 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2019 - Stéphane MOTTELET
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+//
+// <-- CLI SHELL MODE -->
+// <-- NO CHECK REF -->
+//
+// <-- Non-regression test for bug 16087 -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/16087
+//
+// <-- Short Description -->
+// Insertion of struct() in a non-empty struct crashes Scilab
+
+x.a = 1;
+x.b = 2;
+y = x;
+x(1) = struct();
+
+assert_checkequal(x,y)
+