add checkNamedArguments function to get unexpected named arguments.
[scilab.git] / scilab / modules / core / sci_gateway / cpp / sci_checkNamedArguments.cpp
1 /*
2 *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 *  Copyright (C) 2017 - ESI - Antoine ELIAS
4 *
5 * Copyright (C) 2012 - 2016 - Scilab Enterprises
6 *
7 * This file is hereby licensed under the terms of the GNU GPL v2.0,
8 * pursuant to article 5.3.4 of the CeCILL v.2.1.
9 * This file was originally licensed under the terms of the CeCILL v2.1,
10 * and continues to be available under such terms.
11 * For more information, see the COPYING file which you should have received
12 * along with this program.
13 *
14 */
15
16 #include "core_gw.hxx"
17 #include "function.hxx"
18 #include "macro.hxx"
19 #include "context.hxx"
20 #include "double.hxx"
21 #include "string.hxx"
22 #include "configvariable.hxx"
23
24 extern "C"
25 {
26 #include "localization.h"
27 #include "Scierror.h"
28 #include "sciprint.h"
29 }
30
31 const char fname[] = "checkNamedArguments";
32 types::Function::ReturnValue sci_checkNamedArguments(types::typed_list &in, int _iRetCount, types::typed_list &out)
33 {
34     int size = 0;
35     symbol::Context* ctx = symbol::Context::getInstance();
36     int rhs = static_cast<int>(in.size());              
37     std::vector<std::wstring> proto;
38
39     if (ctx->getScopeLevel() < 2)
40     {
41         Scierror(999, _("%s: must be call from a function.\n"), fname);
42         return types::Function::Error;
43     }
44
45     if (rhs != 0)
46     {
47         Scierror(77, _("%s: Wrong number of input argument(s): %d expected.\n"), fname, 0);
48         return types::Function::Error;
49     }
50
51     if (_iRetCount != 1)
52     {
53         Scierror(78, _("%s: Wrong number of output argument(s): %d expected.\n"), fname, 1);
54         return types::Function::Error;
55     }
56
57     //get before last where
58     const ConfigVariable::WhereEntry& where = *(++ConfigVariable::getWhere().crbegin());
59     if (where.call->isMacro())
60     {
61         types::Macro* m = (types::Macro*)where.call;
62         auto inputs = m->getInputs();
63         proto.reserve(inputs->size());
64         for (auto i : *inputs)
65         {
66             std::wstring var(i->getSymbol().getName());
67             if (var != L"varargin")
68             {
69                 proto.push_back(var);
70             }
71         }
72
73         size = (int)proto.size();
74     }
75
76     std::list<std::wstring> lst;
77     int count = ctx->getCurrentScope(lst, true);
78
79         //remove nargin/nargout//varargin
80         lst.remove(L"nargin");
81         lst.remove(L"nargout");
82         lst.remove(L"varargin");
83
84         for (int i = 0; i < size; ++i)
85     {
86                 lst.remove(proto[i]);
87     }
88
89         count = (int)lst.size();
90     if (count == 0)
91     {
92         out.push_back(types::Double::Empty());
93         return types::Function::OK;
94     }
95
96     types::String* pOut = new types::String(count, 1);
97     int i = 0;
98     for (auto v : lst)
99     {
100         pOut->set(i++, v.data());
101     }
102
103     out.push_back(pOut);
104     return types::Function::OK;
105 }