-// Copyright (C) 2007-2012 CEA/DEN, EDF R&D
+// Copyright (C) 2007-2014 CEA/DEN, EDF R&D
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
-// version 2.1 of the License.
+// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
//
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
+// Author : Anthony Geay (CEA/DEN)
#include "InterpKernelExprParser.hxx"
#include "InterpKernelValue.hxx"
#include "InterpKernelAsmX86.hxx"
+#include "InterpKernelAutoPtr.hxx"
#include <cctype>
#include <sstream>
const char ExprParser::EXPR_PARSE_ERR_MSG[]="Invalid expression detected : ";
-LeafExpr *LeafExpr::buildInstanceFrom(const std::string& expr) throw(INTERP_KERNEL::Exception)
+LeafExpr *LeafExpr::buildInstanceFrom(const std::string& expr)
{
std::istringstream stream;
stream.str(expr);
{
}
-void LeafExprVal::fillValue(Value *val) const throw(INTERP_KERNEL::Exception)
+void LeafExprVal::fillValue(Value *val) const
{
val->setDouble(_value);
}
-void LeafExprVal::replaceValues(const std::vector<double>& valuesInExpr) throw(INTERP_KERNEL::Exception)
+void LeafExprVal::replaceValues(const std::vector<double>& valuesInExpr)
{
int pos=(int)_value;
int lgth=(int)valuesInExpr.size();
_value=valuesInExpr[pos];
}
-LeafExprVar::LeafExprVar(const std::string& var):_fast_pos(-1),_var_name(var)
+LeafExprVal *LeafExprVal::deepCpy() const
{
+ return new LeafExprVal(*this);
}
-void LeafExprVar::fillValue(Value *val) const throw(INTERP_KERNEL::Exception)
+LeafExprVar::LeafExprVar(const std::string& var):_fast_pos(-1),_var_name(var),_val(0)
{
- val->setVarname(_fast_pos,_var_name);
}
-void LeafExprVar::prepareExprEvaluation(const std::vector<std::string>& vars, int nbOfCompo, int targetNbOfCompo) const throw(INTERP_KERNEL::Exception)
+void LeafExprVar::fillValue(Value *val) const
+{
+ if(_val)
+ val->setDouble(_val[_fast_pos]);
+ else
+ val->setVarname(_fast_pos,_var_name);
+
+}
+
+void LeafExprVar::prepareExprEvaluation(const std::vector<std::string>& vars, int nbOfCompo, int targetNbOfCompo) const
{
std::vector<std::string>::const_iterator iter=std::find(vars.begin(),vars.end(),_var_name);
if(iter==vars.end())
}
}
-void LeafExprVar::prepareExprEvaluationVec() const throw(INTERP_KERNEL::Exception)
+/*!
+ * \param [in] vars - the sorted list of vars
+ * \param [in] nbOfCompo - the size of the input tuples (it is used to scan if no problem occurs)
+ * \param [in] targetNbOfCompo - the size of the output tuple (it is used to check that no problem occurs)
+ * \param [in] refPos - is an integer in [0,targetNbOfCompo), that tell the id of \a this. It is for multi interpreters.
+ * \sa evaluateDouble
+ */
+void LeafExprVar::prepareExprEvaluationDouble(const std::vector<std::string>& vars, int nbOfCompo, int targetNbOfCompo, int refPos, const double *ptOfInputStart, const double *ptOfInputEnd) const
+{
+ if((int)vars.size()!=std::distance(ptOfInputStart,ptOfInputEnd))
+ throw INTERP_KERNEL::Exception("LeafExprVar::prepareExprEvaluationDouble : size of input vector must be equal to the input vector !");
+ prepareExprEvaluation(vars,nbOfCompo,targetNbOfCompo);
+ _ref_pos=refPos;
+ _val=ptOfInputStart;
+}
+
+void LeafExprVar::prepareExprEvaluationVec() const
{
if(!isRecognizedKeyVar(_var_name,_fast_pos))
_fast_pos=-2;
return true;
}
+LeafExprVar *LeafExprVar::deepCpy() const
+{
+ return new LeafExprVar(*this);
+}
+
/*!
* Nothing to do it is not a bug.
*/
-void LeafExprVar::replaceValues(const std::vector<double>& valuesInExpr) throw(INTERP_KERNEL::Exception)
+void LeafExprVar::replaceValues(const std::vector<double>& valuesInExpr)
{
}
{
}
-ExprParser::ExprParser(const char *expr, ExprParser *father):_father(father),_is_parsed(false),_leaf(0),_is_parsing_ok(false),_expr(expr)
+void ExprParserOfEval::clearSortedMemory()
+{
+ delete _leaf;
+ for(std::vector<ExprParserOfEval>::iterator it=_sub_parts.begin();it!=_sub_parts.end();it++)
+ (*it).clearSortedMemory();
+ for(std::vector<Function *>::iterator it=_funcs.begin();it!=_funcs.end();it++)
+ delete *it;
+}
+
+void ExprParserOfEval::sortMemory()
+{
+ for(std::vector<ExprParserOfEval>::iterator it=_sub_parts.begin();it!=_sub_parts.end();it++)
+ (*it).sortMemory();
+ if(_leaf)
+ _leaf=_leaf->deepCpy();
+ for(std::vector<Function *>::iterator it=_funcs.begin();it!=_funcs.end();it++)
+ if(*it)
+ *it=(*it)->deepCpy();
+}
+
+ExprParser::ExprParser(const std::string& expr, ExprParser *father):_father(father),_is_parsed(false),_leaf(0),_is_parsing_ok(false),_expr(expr)
{
_expr=deleteWhiteSpaces(_expr);
}
ExprParser::~ExprParser()
{
delete _leaf;
+ _for_eval.clearSortedMemory();
releaseFunctions();
}
return ret;
}
-void ExprParser::parse() throw(INTERP_KERNEL::Exception)
+void ExprParser::parse()
{
_is_parsed=true;
_is_parsing_ok=false;
replaceValues(valuesInExpr);
_expr=tmp;
}
+ reverseThis();
_is_parsing_ok=true;
}
-double ExprParser::evaluate() const throw(INTERP_KERNEL::Exception)
+double ExprParser::evaluate() const
{
- Value *gen=new ValueDouble;
- ValueDouble *res=(ValueDouble *)evaluateLowLev(gen);
- delete gen;
- double ret=res->getData();
- delete res;
- return ret;
+ AutoCppPtr<Value> gen(new ValueDouble);
+ AutoCppPtr<ValueDouble> res(static_cast<ValueDouble *>(evaluateLowLev(gen)));
+ return res->getData();
}
-DecompositionInUnitBase ExprParser::evaluateUnit() const throw(INTERP_KERNEL::Exception)
+DecompositionInUnitBase ExprParser::evaluateUnit() const
{
Value *gen=new ValueUnit;
ValueUnit *res=0;
return ret;
}
-void ExprParser::evaluateExpr(int szOfOutParam, const double *inParam, double *outParam) const throw(INTERP_KERNEL::Exception)
+void ExprParser::evaluateExpr(int szOfOutParam, const double *inParam, double *outParam) const
{
- Value *gen=new ValueDoubleExpr(szOfOutParam,inParam);
- ValueDoubleExpr *res=0;
- try
- {
- res=(ValueDoubleExpr *)evaluateLowLev(gen);
- }
- catch(INTERP_KERNEL::Exception& e)
- {
- delete gen;
- throw e;
- }
- delete gen;
+ AutoCppPtr<Value> gen(new ValueDoubleExpr(szOfOutParam,inParam));
+ AutoCppPtr<ValueDoubleExpr> res(static_cast<ValueDoubleExpr *>(evaluateLowLev(gen)));
std::copy(res->getData(),res->getData()+szOfOutParam,outParam);
- delete res;
}
-void ExprParser::prepareExprEvaluation(const std::vector<std::string>& vars, int nbOfCompo, int targetNbOfCompo) const throw(INTERP_KERNEL::Exception)
+void ExprParser::prepareExprEvaluation(const std::vector<std::string>& vars, int nbOfCompo, int targetNbOfCompo) const
{
if(_leaf)
{
leafC->prepareExprEvaluation(vars,nbOfCompo,targetNbOfCompo);
}
else
- for(std::list<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
+ for(std::vector<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
(*iter).prepareExprEvaluation(vars,nbOfCompo,targetNbOfCompo);
}
-void ExprParser::prepareExprEvaluationVec() const throw(INTERP_KERNEL::Exception)
+/*!
+ * \param [in] vars - the sorted list of vars
+ * \param [in] nbOfCompo - the size of the input tuples (it is used to scan if no problem occurs)
+ * \param [in] targetNbOfCompo - the size of the output tuple (it is used to check that no problem occurs)
+ * \param [in] refPos - is an integer in [0,targetNbOfCompo), that tell the id of \a this. It is for multi interpreters.
+ * \sa evaluateDouble
+ */
+void ExprParser::prepareExprEvaluationDouble(const std::vector<std::string>& vars, int nbOfCompo, int targetNbOfCompo, int refPos, const double *ptOfInputStart, const double *ptOfInputEnd) const
+{
+ if((int)vars.size()!=std::distance(ptOfInputStart,ptOfInputEnd))
+ throw INTERP_KERNEL::Exception("ExprParser::prepareExprEvaluationDouble : size of input vector must be equal to the input vector !");
+ if(_leaf)
+ {
+ LeafExprVar *leafC=dynamic_cast<LeafExprVar *>(_leaf);
+ if(leafC)
+ leafC->prepareExprEvaluationDouble(vars,nbOfCompo,targetNbOfCompo,refPos,ptOfInputStart,ptOfInputEnd);
+ }
+ else
+ for(std::vector<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
+ (*iter).prepareExprEvaluationDouble(vars,nbOfCompo,targetNbOfCompo,refPos,ptOfInputStart,ptOfInputEnd);
+}
+
+void ExprParser::prepareFastEvaluator() const
+{
+ _for_eval.clearSortedMemory();
+ _for_eval=convertMeTo();
+ _for_eval.sortMemory();
+}
+
+/*!
+ * \sa prepareExprEvaluationDouble
+ */
+double ExprParser::evaluateDouble() const
+{
+ checkForEvaluation();
+ std::vector<double> stackOfVal;
+ evaluateDoubleInternal(stackOfVal);
+ return stackOfVal.back();
+}
+
+void ExprParser::checkForEvaluation() const
+{
+ if(!_is_parsing_ok)
+ throw INTERP_KERNEL::Exception("checkForEvaluation : Parsing fails ! Invalid expression !");
+ if(_sub_expr.empty() && !_leaf)
+ throw INTERP_KERNEL::Exception("checkForEvaluation : Empty expression !");
+}
+
+void ExprParser::prepareExprEvaluationVec() const
{
std::set<std::string> trueVars;
getTrueSetOfVars(trueVars);
prepareExprEvaluationVecLowLev();
}
-void ExprParser::prepareExprEvaluationVecLowLev() const throw(INTERP_KERNEL::Exception)
+void ExprParser::prepareExprEvaluationVecLowLev() const
{
if(_leaf)
{
leafC->prepareExprEvaluationVec();
}
else
- for(std::list<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
+ for(std::vector<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
(*iter).prepareExprEvaluationVecLowLev();
}
-Value *ExprParser::evaluateLowLev(Value *valGen) const throw(INTERP_KERNEL::Exception)
+Value *ExprParser::evaluateLowLev(Value *valGen) const
{
- if(!_is_parsing_ok)
- throw INTERP_KERNEL::Exception("Parsing fails ! Invalid expression !");
- if(_sub_expr.empty() && !_leaf)
- throw INTERP_KERNEL::Exception("Empty expression !");
+ checkForEvaluation();
std::vector<Value *> stackOfVal;
try
{
else
{
stackOfVal.resize(_sub_expr.size());
- std::vector<Value *>::reverse_iterator iter2=stackOfVal.rbegin();
- for(std::list<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++,iter2++)
+ std::vector<Value *>::iterator iter2=stackOfVal.begin();
+ for(std::vector<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++,iter2++)
*iter2=(*iter).evaluateLowLev(valGen);
}
- std::list<Function *>::const_iterator iter3;
- for(iter3=_func_btw_sub_expr.begin();iter3!=_func_btw_sub_expr.end();iter3++)
+ for(std::vector<Function *>::const_iterator iter3=_func_btw_sub_expr.begin();iter3!=_func_btw_sub_expr.end();iter3++)
(*iter3)->operate(stackOfVal);
}
catch(INTERP_KERNEL::Exception& e)
return stackOfVal.back();
}
+void ExprParser::reverseThis()
+{
+ if(_leaf)
+ return ;
+ for(std::vector<ExprParser>::iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
+ (*iter).reverseThis();
+ AutoPtr<char> buf(new char[sizeof(ExprParser)]);
+ char *loc(reinterpret_cast<char *>(&_sub_expr[0])),*bufPtr(buf);
+ std::size_t sz(_sub_expr.size());
+ std::size_t nbOfTurn(sz/2);
+ for(std::size_t i=0;i<nbOfTurn;i++)
+ {
+ std::copy(loc+i*sizeof(ExprParser),loc+(i+1)*sizeof(ExprParser),bufPtr);
+ std::copy(loc+(sz-i-1)*sizeof(ExprParser),loc+(sz-i)*sizeof(ExprParser),loc+i*sizeof(ExprParser));
+ std::copy(bufPtr,bufPtr+sizeof(ExprParser),loc+(sz-i-1)*sizeof(ExprParser));
+ }
+}
+
+ExprParserOfEval ExprParser::convertMeTo() const
+{
+ std::size_t sz(_sub_expr.size());
+ std::vector<ExprParserOfEval> subExpr(sz);
+ for(std::size_t i=0;i<sz;i++)
+ subExpr[i]=_sub_expr[i].convertMeTo();
+ return ExprParserOfEval(_leaf,subExpr,_func_btw_sub_expr);
+}
+
void ExprParser::getSetOfVars(std::set<std::string>& vars) const
{
if(_leaf)
vars.insert(leafC->getVar());
}
else
- for(std::list<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
+ for(std::vector<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
(*iter).getSetOfVars(vars);
}
}
}
-void ExprParser::parseDeeper() throw(INTERP_KERNEL::Exception)
+void ExprParser::parseDeeper()
{
- for(std::list<ExprParser>::iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
+ for(std::vector<ExprParser>::iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
if(!(*iter).simplify())
(*iter).parseDeeper();
}
* Something defined as the contain of highest level barckets.
* Typically '(3*x+2)' and 'cos(4*l+p*n)' will be intercepted by this method whereas '3*x+2' not...etc..
*/
-void ExprParser::parseUnaryFunc() throw(INTERP_KERNEL::Exception)
+void ExprParser::parseUnaryFunc()
{
if(_expr[_expr.length()-1]!=')')
return ;
* \return true if no recursion needed, false if this->_expr is too complex to be interpreted at this level.
* \throw exception if this->_expr is simple enough to try to interprate this and this expression contains an error.
*/
-bool ExprParser::tryToInterpALeaf() throw(INTERP_KERNEL::Exception)
+bool ExprParser::tryToInterpALeaf()
{
std::size_t pos=_expr.find_first_not_of("+-",0,2);
std::string minimizedExpr=_expr.substr(pos);
return true;
}
-void ExprParser::parseForCmp() throw(INTERP_KERNEL::Exception)
+void ExprParser::parseForCmp()
{
std::string::const_iterator iter;
int curLevel=0;
}
}
-void ExprParser::parseForAddMin() throw(INTERP_KERNEL::Exception)
+void ExprParser::parseForAddMin()
{
std::string::const_iterator iter;
int curLevel=0;
}
}
-void ExprParser::parseForMulDiv() throw(INTERP_KERNEL::Exception)
+void ExprParser::parseForMulDiv()
{
std::string::const_iterator iter;
int curLevel=0;
}
}
-void ExprParser::parseForPow() throw(INTERP_KERNEL::Exception)
+void ExprParser::parseForPow()
{
std::string::const_iterator iter;
int curLevel=0;
void ExprParser::releaseFunctions()
{
- for(std::list<Function *>::iterator iter=_func_btw_sub_expr.begin();iter!=_func_btw_sub_expr.end();iter++)
+ for(std::vector<Function *>::iterator iter=_func_btw_sub_expr.begin();iter!=_func_btw_sub_expr.end();iter++)
delete *iter;
_func_btw_sub_expr.clear();
}
* This method first try to see if this->_expr is a leaf, if not it try a unary function of something (see INTERP_KERNEL::ExprParser::parseUnaryFunc method)
* If true is returned, no deeper parsing needed, if false is returned for a full parsing of this->_expr INTERP_KERNEL::ExprParser::parseDeeper call needed.
*/
-bool ExprParser::simplify() throw(INTERP_KERNEL::Exception)
+bool ExprParser::simplify()
{
if(tryToInterpALeaf())
return true;
return false;
}
-void ExprParser::checkBracketsParity() const throw(INTERP_KERNEL::Exception)
+void ExprParser::checkBracketsParity() const
{
std::string::const_iterator iter;
int curLevel=0;
* If double representation is invalid an exception is thrown.
* This method returns a delta that is the delta to operate to pos in expr after substitution.
*/
-double ExprParser::ReplaceAndTraduce(std::string& expr, int id, std::size_t bg, std::size_t end, int& delta) throw(INTERP_KERNEL::Exception)
+double ExprParser::ReplaceAndTraduce(std::string& expr, int id, std::size_t bg, std::size_t end, int& delta)
{
static const char MSG[]="Interal error : A string expected to be a float is not one ! Bug to signal !";
std::istringstream stream;
* This method scans _expr finding in greedy mode the following pattern :
* {0..9}+{.}?{0..9}*{{eE}{-}?{0..9}+}?
*/
-void ExprParser::fillValuesInExpr(std::vector<double>& valuesInExpr) throw(INTERP_KERNEL::Exception)
+void ExprParser::fillValuesInExpr(std::vector<double>& valuesInExpr)
{
const char FIGURES[]="0123456789";
const std::string other("+-*^/(<>,");
}
}
-void ExprParser::replaceValues(const std::vector<double>& valuesInExpr) throw(INTERP_KERNEL::Exception)
+void ExprParser::replaceValues(const std::vector<double>& valuesInExpr)
{
if(_leaf)
_leaf->replaceValues(valuesInExpr);
else
{
- for(std::list<ExprParser>::iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
+ for(std::vector<ExprParser>::iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
(*iter).replaceValues(valuesInExpr);
}
}
_leaf->compileX86(ass);
else
{
- for(std::list<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
+ for(std::vector<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
(*iter).compileX86LowLev(ass);
}
- for(std::list<Function *>::const_iterator iter2=_func_btw_sub_expr.begin();iter2!=_func_btw_sub_expr.end();iter2++)
+ for(std::vector<Function *>::const_iterator iter2=_func_btw_sub_expr.begin();iter2!=_func_btw_sub_expr.end();iter2++)
(*iter2)->operateX86(ass);
}
_leaf->compileX86_64(ass);
else
{
- for(std::list<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
+ for(std::vector<ExprParser>::const_iterator iter=_sub_expr.begin();iter!=_sub_expr.end();iter++)
(*iter).compileX86_64LowLev(ass);
}
- for(std::list<Function *>::const_iterator iter2=_func_btw_sub_expr.begin();iter2!=_func_btw_sub_expr.end();iter2++)
+ for(std::vector<Function *>::const_iterator iter2=_func_btw_sub_expr.begin();iter2!=_func_btw_sub_expr.end();iter2++)
(*iter2)->operateX86(ass);
}
+double LeafExprVal::getDoubleValue() const
+{
+ return _value;
+}
+
void LeafExprVal::compileX86(std::vector<std::string>& ass) const
{
ass.push_back("sub esp,8");
- int *b=(int *)&_value,*c=(int *)&_value;
+ const int *b=reinterpret_cast<const int *>(&_value),*c=reinterpret_cast<const int *>(&_value);
c++;
std::ostringstream oss;
oss << std::hex;
void LeafExprVal::compileX86_64(std::vector<std::string>& ass) const
{
ass.push_back("sub rsp,8");
- int *b=(int *)&_value,*c=(int *)&_value;
+ const int *b=reinterpret_cast<const int *>(&_value),*c=reinterpret_cast<const int *>(&_value);
c++;
std::ostringstream oss;
oss << std::hex;
ass.push_back("add rsp,8");
}
+double LeafExprVar::getDoubleValue() const
+{
+ if(_fast_pos>=0)
+ return _val[_fast_pos];
+ else
+ {
+ int pos(-7-_fast_pos);
+ return pos==_ref_pos?1.:0.;
+ }
+}
+
void LeafExprVar::compileX86(std::vector<std::string>& ass) const
{
ass.push_back("fld qword [ebp+8]");
{
int sz=_father->getStackSizeToPlayX86(this);
int i=0;
- for(std::list<ExprParser>::const_reverse_iterator iter=_sub_expr.rbegin();iter!=_sub_expr.rend();iter++,i++)
+ for(std::vector<ExprParser>::const_reverse_iterator iter=_sub_expr.rbegin();iter!=_sub_expr.rend();iter++,i++)
{
const ExprParser& obj=(*iter);
const ExprParser *pt=&obj;