2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2009-2009 - DIGITEO - Bruno JOFRET
5 * This file must be used under the terms of the CeCILL.
6 * This source file is licensed as described in the file COPYING, which
7 * you should have received as part of this distribution. The terms
8 * are also available at
9 * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
18 #include "context.hxx"
20 #include "localization.h"
21 #include "scilabWrite.hxx"
22 #include "scilabexception.hxx"
23 #include "configvariable.hxx"
24 #include "mutevisitor.hxx"
30 #include "os_swprintf.h"
35 Macro::Macro(const std::wstring& _stName, std::list<symbol::Symbol> &_inputArgs, std::list<symbol::Symbol> &_outputArgs, ast::SeqExp &_body, const wstring& _stModule):
36 Callable(), m_inputArgs(&_inputArgs), m_outputArgs(&_outputArgs), m_body(&_body),
37 m_ArgInSymb(symbol::Symbol(L"nargin")), m_ArgOutSymb(symbol::Symbol(L"nargout"))
42 m_pDblArgIn = new Double(1);
43 m_pDblArgIn->IncreaseRef(); //never delete
44 m_pDblArgOut = new Double(1);
45 m_pDblArgOut->IncreaseRef(); //never delete
53 InternalType* Macro::clone()
61 std::cout << "types::Macro";
64 InternalType::RealType Macro::getType(void)
69 ast::SeqExp* Macro::getBody(void)
74 bool Macro::toString(std::wostringstream& ostr)
76 ostr << L"FIXME : Implement Macro::toString" << std::endl;
80 Callable::ReturnValue Macro::call(typed_list &in, optional_list &opt, int _iRetCount, typed_list &out, ast::ConstVisitor* execFunc)
82 bool bVarargout = false;
83 ReturnValue RetVal = Callable::OK;
84 symbol::Context *pContext = symbol::Context::getInstance();
87 pContext->scope_begin();
89 //add optional paramter in current scope
90 optional_list::const_iterator it;
91 for (it = opt.begin() ; it != opt.end() ; it++)
93 pContext->put(symbol::Symbol(it->first), *it->second);
95 //check excepted and input/output parameters numbers
96 // Scilab Macro can be called with less than prototyped arguments,
97 // but not more execpts with varargin
99 // varargin management
100 if (m_inputArgs->size() > 0 && m_inputArgs->back().name_get() == L"varargin")
102 int iVarPos = static_cast<int>(in.size());
103 if (iVarPos > static_cast<int>(m_inputArgs->size()) - 1)
105 iVarPos = static_cast<int>(m_inputArgs->size()) - 1;
108 //add all standard variable in function context but not varargin
109 std::list<symbol::Symbol>::const_iterator itName = m_inputArgs->begin();
110 typed_list::const_iterator itValue = in.begin();
113 pContext->put((*itName), **itValue);
119 //create varargin only if previous variable are assigned
120 if (in.size() >= m_inputArgs->size() - 1)
122 //create and fill varargin
123 List* pL = new List();
124 while (itValue != in.end())
126 pL->append(*itValue);
129 pContext->put(symbol::Symbol(L"varargin"), *pL);
132 else if (in.size() > m_inputArgs->size())
135 ostr << _W("Wrong number of input arguments.") << std::endl << std::endl;
136 ostr << _W("Excepted: ") << m_inputArgs->size() << std::endl;
138 if (m_inputArgs->size() > 0)
140 ostr << _W("Arguments are:") << std::endl << std::endl;
142 for (std::list<symbol::Symbol>::iterator it = m_inputArgs->begin() ; it != m_inputArgs->end() ; ++it)
144 ostr << (*it).name_get() << L" ";
149 char* pst = wide_string_to_UTF8(ostr.str().c_str());
150 Scierror(58, "%s", pst);
151 pContext->scope_end();
152 return Callable::Error;
156 //assign value to variable in the new context
157 std::list<symbol::Symbol>::const_iterator i;
158 typed_list::const_iterator j;
160 for (i = m_inputArgs->begin(), j = in.begin(); j != in.end (); ++j, ++i)
162 pContext->put((*i), **j);
166 // varargout management
168 // varargout must be alone
169 // varargout is a list
170 // varargout can containt more items than caller need
171 // varargout must containt at leat caller needs
172 if (m_outputArgs->size() == 1 && m_outputArgs->back().name_get() == L"varargout")
175 List* pL = new List();
176 pContext->put(symbol::Symbol(L"varargout"), *pL);
179 //common part with or without varargin/varargout
181 // Declare nargin & nargout in function context.
182 m_pDblArgIn->set(0, static_cast<double>(in.size()));
183 m_pDblArgOut->set(0, _iRetCount);
184 pContext->put(m_ArgInSymb, *m_pDblArgIn);
185 pContext->put(m_ArgOutSymb, *m_pDblArgOut);
187 //save current prompt mode
188 int oldVal = ConfigVariable::getPromptMode();
193 //m_body->accept(mute);
195 ConfigVariable::setPromptMode(-1);
196 m_body->returnable_set();
197 m_body->accept(*execFunc);
198 //restore previous prompt mode
199 ConfigVariable::setPromptMode(oldVal);
200 if (m_body->is_return())
202 m_body->returnable_set();
205 //varargout management
208 InternalType* pOut = pContext->get(symbol::Symbol(L"varargout"));
211 Scierror(999, _("Invalid index.\n"));
212 return Callable::Error;
215 if (pOut->isList() == false || pOut->getAs<List>()->getSize() == 0)
217 Scierror(999, _("Invalid index.\n"));
218 return Callable::Error;
221 List* pVarOut = pOut->getAs<List>();
222 for (int i = 0 ; i < Min(pVarOut->getSize(), _iRetCount) ; i++)
224 InternalType* pIT = pVarOut->get(i)->clone();
225 if (pIT->isListUndefined())
227 Scierror(999, _("List element number %d is Undefined.\n"), i + 1);
228 return Callable::Error;
236 //normal output management
237 std::list<symbol::Symbol>::const_iterator i;
238 for (i = m_outputArgs->begin(); i != m_outputArgs->end() && _iRetCount; ++i, --_iRetCount)
240 InternalType *pIT = pContext->get((*i));
248 char* pst = wide_string_to_UTF8((*i).name_get().c_str());
249 Scierror(999, _("Undefined variable %s.\n"), pst);
251 return Callable::Error;
256 catch (ast::ScilabMessage se)
258 //restore previous prompt mode
259 ConfigVariable::setPromptMode(oldVal);
260 //close the current scope
261 pContext->scope_end();
262 for (size_t j = 0; j < out.size(); ++j)
264 out[j]->DecreaseRef();
268 catch (ast::InternalAbort sa)
270 //restore previous prompt mode
271 ConfigVariable::setPromptMode(oldVal);
272 //close the current scope
273 pContext->scope_end();
274 for (size_t j = 0; j < out.size(); ++j)
276 out[j]->DecreaseRef();
281 //close the current scope
282 pContext->scope_end();
284 for (size_t j = 0; j < out.size(); ++j)
286 out[j]->DecreaseRef();
291 std::list<symbol::Symbol>* Macro::inputs_get()
296 std::list<symbol::Symbol>* Macro::outputs_get()