{
}
-QVariant BinaryOperator::execute ( const QVariant&op1,const QVariant&op2 ) const
+QVariant BinaryOperator::execute ( const QVariant&op1,const QVariant&op2,Engine&eng) const
{
//search for match
QPair<int,int>k(op1.userType(),op2.userType());
if(bc==0)
return Exception(Exception::TypeMismatchError, "operator cannot work on this type");
//execute
- return bc(op1,op2);
+ return bc(op1,op2,eng);
}
BinaryOperatorCall BinaryOperator::getCallback ( QString type1, QString type2 ) const
#include "dptr.h"
namespace ELAM {
+class Engine;
/** \brief pointer to a function wrapping a binary operator
\param op1 the left operand
\param op2 the right operand
+\param engine the engine calling the operator
\returns the result of the operation*/
-typedef QVariant (*BinaryOperatorCall)(const QVariant&op1,const QVariant&op2);
+typedef QVariant (*BinaryOperatorCall)(const QVariant&op1,const QVariant&op2,Engine&engine);
/** \brief Wraps a particular binary operator.
QList<QPair<int,int> > getTypeIds()const;
///calls the callback function associated with the type of the argument, throws an exception if there is no callback
- QVariant execute(const QVariant&,const QVariant&)const;
+ QVariant execute(const QVariant&,const QVariant&,Engine&)const;
///true if this operator has no callbacks
bool isNull()const;
}
-static QVariant boolFunc(const QList<QVariant>&lf)
+static QVariant boolFunc(const QList<QVariant>&lf,Engine&)
{
if(lf.size()!=1)
return Exception(Exception::ArgumentListError, "expecting exactly one argument");
}
//unary
-static QVariant boolNot(const QVariant&o)
+static QVariant boolNot(const QVariant&o,Engine&)
{
return !o.toBool();
}
//bitwise
-static QVariant boolAnd(const QVariant&o1,const QVariant&o2)
+static QVariant boolAnd(const QVariant&o1,const QVariant&o2,Engine&)
{
return o1.toBool()&&o2.toBool();
}
-static QVariant boolOr(const QVariant&o1,const QVariant&o2)
+static QVariant boolOr(const QVariant&o1,const QVariant&o2,Engine&)
{
return o1.toBool()||o2.toBool();
}
-static QVariant boolXor(const QVariant&o1,const QVariant&o2)
+static QVariant boolXor(const QVariant&o1,const QVariant&o2,Engine&)
{
return o1.toBool()^o2.toBool();
}
-QVariant boolCast(const QVariant&v){return v.toBool();}
+QVariant boolCast(const QVariant&v,const Engine&){return v.toBool();}
void BoolEngine::configureBoolEngine(Engine&eng)
{
eng.binaryOperator("^^",25).setCallback(boolXor,bid,bid);
}
-static QVariant ifFunc(const QList<QVariant>&lf)
+static QVariant ifFunc(const QList<QVariant>&lf,Engine&)
{
if(lf.size()<2 || lf.size()>3)
return Exception(Exception::ArgumentListError, "expecting 2 or 3 arguments");
return QVariant();
}
-static QVariant isNullFunc(const QList<QVariant>&lf)
+static QVariant isNullFunc(const QList<QVariant>&lf,Engine&)
{
if(lf.size()!=1)
return Exception(Exception::ArgumentListError, "expecting exactly one argument");
return lf[0].isNull();
}
-static QVariant isExceptionFunc(const QList<QVariant>&lf)
+static QVariant isExceptionFunc(const QList<QVariant>&lf,Engine&)
{
if(lf.size()!=1)
return Exception(Exception::ArgumentListError, "expecting exactly one argument");
return lf[0].userType()==Exception::metaTypeId();
}
-static QVariant isExceptionOrNullFunc(const QList<QVariant>&lf)
+static QVariant isExceptionOrNullFunc(const QList<QVariant>&lf,Engine&)
{
if(lf.size()!=1)
return Exception(Exception::ArgumentListError, "expecting exactly one argument");
return lf[0].isNull() || lf[0].userType()==Exception::metaTypeId();
}
-static QVariant catchFunc(const QList<QVariant>&lf)
+static QVariant catchFunc(const QList<QVariant>&lf,Engine&)
{
if(lf.size()<1||lf.size()>3)
return Exception(Exception::ArgumentListError, "expecting 1-3 arguments");
QVariant Engine::getValue(QString n) const
{
- if(d->consts.contains(n))return d->consts[n];
- if(d->vars.contains(n))return d->vars[n];
+ if(hasConstant(n))return getConstant(n);
+ if(hasVariable(n))return getVariable(n);
return QVariant();
}
bool Engine::hasValue(QString n) const
{
- return d->vars.contains(n) || d->consts.contains(n);
+ return hasVariable(n) || hasConstant(n);
}
void Engine::removeConstant(QString n)
void Engine::removeValue(QString n)
{
- d->consts.remove(n);
- d->vars.remove(n);
+ removeConstant(n);
+ removeVariable(n);
}
bool Engine::setConstant(QString n, QVariant v)
{
if(!d->cclass.isName(n))return false;
if(d->funcs.contains(n))return false;
- d->vars.remove(n);
+ removeVariable(n);
d->consts.insert(n,autoCast(v));
return true;
}
bool Engine::setVariable(QString n, QVariant v)
{
if(!d->cclass.isName(n))return false;
- if(d->consts.contains(n))return false;
+ if(hasConstant(n))return false;
if(d->funcs.contains(n))return false;
d->vars.insert(n,autoCast(v));
return true;
{
if(p==0)return false;
if(!d->cclass.isName(n))return false;
- if(d->consts.contains(n))return false;
- if(d->vars.contains(n))return false;
+ if(hasConstant(n))return false;
+ if(hasVariable(n))return false;
d->funcs.insert(n,p);
return true;
}
}
//found it?
if(pos<0)return v;
- else return d->casts[pos].cfunc(v);
+ else return d->casts[pos].cfunc(v,*this);
}
QStringList Engine::binaryOperatorNames() const
namespace ELAM {
+class Engine;
+
/**pointer to a function wrapping a mathematical function
\param args the list of arguments
\returns the result of the function or ELAM::Exception in case or errors
Functions must check their arguments for validity before they start calculating. On error a function should returns an ELAM::Exception.
-*/
-typedef QVariant (*Function)(const QList<QVariant>&args);
+\param args the list of arguments that was given to the function, the implementation must check for length and type of the arguments
+\param engine the engine calling the function
+*/
+typedef QVariant (*Function)(const QList<QVariant>&args,Engine&engine);
-class Engine;
/**wraps the parser routine for a literal
\param expr the original expression string
/**Wraps a cast function to convert various types into another type.
\param orig the original value of any type
-\returns the converted value that must conform to the expected type*/
-typedef QVariant (*TypeCast)(const QVariant&orig);
+\param engine the engine calling the cast
+\returns the converted value that conforms to the expected type*/
+typedef QVariant (*TypeCast)(const QVariant&orig,const Engine&engine);
/**The calculation engine of .
Engine(QObject*parent=0);
///true if the named variable exists in this engine
- Q_INVOKABLE bool hasVariable(QString)const;
+ Q_INVOKABLE virtual bool hasVariable(QString)const;
///true if the named constant exists in this engine
- Q_INVOKABLE bool hasConstant(QString)const;
+ Q_INVOKABLE virtual bool hasConstant(QString)const;
///true if a variable or constant of that name exists in this engine
- Q_INVOKABLE bool hasValue(QString)const;
+ ///(default calls hasVariable() || hasConstant() )
+ Q_INVOKABLE virtual bool hasValue(QString)const;
///returns true if the named function exists
Q_INVOKABLE bool hasFunction(QString)const;
Q_INVOKABLE QVariant autoCast(const QVariant&)const;
///returns the names of all currently existing variables
- Q_INVOKABLE QStringList variableNames()const;
+ Q_INVOKABLE virtual QStringList variableNames()const;
///returns the names of all currently existing constants
- Q_INVOKABLE QStringList constantNames()const;
+ Q_INVOKABLE virtual QStringList constantNames()const;
///returns the names of all currently existing functions
Q_INVOKABLE QStringList functionNames()const;
///returns the names of all currently existing binary operators
public slots:
///returns the value of the named variable or constant
- QVariant getValue(QString)const;
+ ///(default uses getVariable/getConstant)
+ virtual QVariant getValue(QString)const;
///returns the value of the named variable (does not return constants)
- QVariant getVariable(QString)const;
+ virtual QVariant getVariable(QString)const;
///returns the value of the named constant (does not return variables)
- QVariant getConstant(QString)const;
+ virtual QVariant getConstant(QString)const;
/**sets a variable
- the name is not valid
- a function or constant of that name already exists
*/
- bool setVariable(QString,QVariant);
+ virtual bool setVariable(QString,QVariant);
/**sets a constant
\returns true on success or false if:
- a function of that name exists
Constants overwrite variables - if a variable of the same name exists, it is transparently deleted before the constant is created.*/
- bool setConstant(QString,QVariant);
+ virtual bool setConstant(QString,QVariant);
- ///deletes a variable (does not affect constants)
- void removeVariable(QString);
- ///deletes a constant (does not affect variables)
- void removeConstant(QString);
+ ///deletes a variable (does not affect constants, does nothing if the variable does not exist)
+ virtual void removeVariable(QString);
+ ///deletes a constant (does not affect variables, does nothing if the constant does not exist)
+ virtual void removeConstant(QString);
///deletes a variable or constant
- void removeValue(QString);
+ ///(default uses removeVariable and removeConstant)
+ virtual void removeValue(QString);
/**Sets a new function for a specific function name.
If there already is a function of that name it is overridden.
//get operator
BinaryOperator binop=d->parent->binaryOperator(un);
//perform operation
- QVariant r=binop.execute(sub1,sub2);
+ QVariant r=binop.execute(sub1,sub2,*(d->parent));
if(r.userType()==Exception::metaTypeId()){
ELAM::Exception ex=r;
if(!ex.position().isValid())
for(int i=0;i<d->subexpr.size();i++)
args<<d->parent->autoCast(d->subexpr[i].evaluate());
//execute
- return func(args);
+ return func(args,*(d->parent));
}
QVariant Expression::evalUnary()
//get operator
UnaryOperator unop=d->parent->unaryOperator(un);
//perform operation
- return unop.execute(sub);
+ return unop.execute(sub,*(d->parent));
}
else return QPair<QString,QVariant>();
}
-static QVariant floatAdd(const QVariant &o1,const QVariant &o2)
+static QVariant floatAdd(const QVariant &o1,const QVariant &o2,Engine&)
{
return o1.toDouble()+o2.toDouble();
}
-static QVariant floatPlus(const QVariant &o)
+static QVariant floatPlus(const QVariant &o,Engine&)
{
return o;
}
-static QVariant floatMinus(const QVariant &o)
+static QVariant floatMinus(const QVariant &o,Engine&)
{
return -o.toDouble();
}
-static QVariant floatMinus(const QVariant &o1,const QVariant &o2)
+static QVariant floatMinus(const QVariant &o1,const QVariant &o2,Engine&)
{
return o1.toDouble()-o2.toDouble();
}
-static QVariant floatMult(const QVariant &o1,const QVariant &o2)
+static QVariant floatMult(const QVariant &o1,const QVariant &o2,Engine&)
{
return o1.toDouble()*o2.toDouble();
}
-static QVariant floatDiv(const QVariant &o1,const QVariant &o2)
+static QVariant floatDiv(const QVariant &o1,const QVariant &o2,Engine&)
{
double d2=o2.toDouble();
if(d2==0.0)
return o1.toDouble()/d2;
}
-static QVariant floatFunc(const QList<QVariant>&lf)
+static QVariant floatFunc(const QList<QVariant>&lf,Engine&)
{
if(lf.size()!=1)
return Exception(Exception::ArgumentListError, "expecting exactly one argument");
return 10;
}
-static QVariant fltCast(const QVariant&v){return v.toDouble();}
+static QVariant fltCast(const QVariant&v,const Engine&){return v.toDouble();}
void FloatEngine::configureFloatEngine(ELAM::Engine& eng)
{
else return QPair<QString,QVariant>();
}
-static QVariant intFunc(const QList<QVariant>&lf)
+static QVariant intFunc(const QList<QVariant>&lf,Engine&)
{
if(lf.size()!=1)
return Exception(Exception::ArgumentListError, "expecting exactly one argument");
}
//unary
-static QVariant intPlus(const QVariant&o)
+static QVariant intPlus(const QVariant&o,Engine&)
{
return o;
}
-static QVariant intMinus(const QVariant&o)
+static QVariant intMinus(const QVariant&o,Engine&)
{
return -o.toLongLong();
}
//additive
-static QVariant intAdd(const QVariant&o1,const QVariant&o2)
+static QVariant intAdd(const QVariant&o1,const QVariant&o2,Engine&)
{
return o1.toLongLong()+o2.toLongLong();
}
-static QVariant intMinus(const QVariant&o1,const QVariant&o2)
+static QVariant intMinus(const QVariant&o1,const QVariant&o2,Engine&)
{
return o1.toLongLong()-o2.toLongLong();
}
//multiplicative
-static QVariant intMult(const QVariant&o1,const QVariant&o2)
+static QVariant intMult(const QVariant&o1,const QVariant&o2,Engine&)
{
return o1.toLongLong()*o2.toLongLong();
}
-static QVariant intDiv(const QVariant&o1,const QVariant&o2)
+static QVariant intDiv(const QVariant&o1,const QVariant&o2,Engine&)
{
qlonglong l2=o2.toLongLong();
if(l2==0)
return Exception(Exception::OperationError,"division by zero");
return o1.toLongLong()/l2;
}
-static QVariant intMod(const QVariant&o1,const QVariant&o2)
+static QVariant intMod(const QVariant&o1,const QVariant&o2,Engine&)
{
qlonglong l2=o2.toLongLong();
if(l2==0)
}
//bitwise
-static QVariant intAnd(const QVariant&o1,const QVariant&o2)
+static QVariant intAnd(const QVariant&o1,const QVariant&o2,Engine&)
{
return o1.toLongLong()&o2.toLongLong();
}
-static QVariant intOr(const QVariant&o1,const QVariant&o2)
+static QVariant intOr(const QVariant&o1,const QVariant&o2,Engine&)
{
return o1.toLongLong()|o2.toLongLong();
}
-static QVariant intXor(const QVariant&o1,const QVariant&o2)
+static QVariant intXor(const QVariant&o1,const QVariant&o2,Engine&)
{
return o1.toLongLong()^o2.toLongLong();
}
-static QVariant intNot(const QVariant&o)
+static QVariant intNot(const QVariant&o,Engine&)
{
return ~o.toLongLong();
}
return 20;
}
-static QVariant intCast(const QVariant&v){return v.toLongLong();}
+static QVariant intCast(const QVariant&v,const Engine&){return v.toLongLong();}
void IntEngine::configureIntEngine(ELAM::Engine& eng)
{
return QPair<QString,QVariant>(ls,r);
}
-static QVariant strFunc(const QList<QVariant>&lf)
+static QVariant strFunc(const QList<QVariant>&lf,Engine&)
{
if(lf.size()!=1)
return Exception(Exception::ArgumentListError, "expecting exactly one argument");
return lf[0].toString();
}
-static QVariant strlenFunc(const QList<QVariant>&lf)
+static QVariant strlenFunc(const QList<QVariant>&lf,Engine&)
{
if(lf.size()!=1)
return Exception(Exception::ArgumentListError, "expecting exactly one argument");
return (qlonglong)lf[0].toString().size();
}
-static QVariant concatFunc(const QList<QVariant>&lf)
+static QVariant concatFunc(const QList<QVariant>&lf,Engine&)
{
QString ret;
for(int i=0;i<lf.size();i++)
return ret;
}
//additive
-static QVariant strAdd(const QVariant&o1,const QVariant&o2)
+static QVariant strAdd(const QVariant&o1,const QVariant&o2,Engine&)
{
return o1.toString()+o2.toString();
}
return 50;
}
-static QVariant strCast(const QVariant&v){return v.toString();}
+static QVariant strCast(const QVariant&v,const Engine&){return v.toString();}
void StringEngine::configureStringEngine(Engine& eng)
{
}
-QVariant UnaryOperator::execute(const QVariant& op) const
+QVariant UnaryOperator::execute(const QVariant& op,Engine&eng) const
{
if(d->callmap.size()==0)
return Exception(Exception::UnknownOperatorError);
//search for direct match
if(d->callmap.contains(op.userType()))
- return d->callmap[op.userType()](op);
+ return d->callmap[op.userType()](op,eng);
//search for fallback
int any=AnyType::metaTypeId();
if(d->callmap.contains(any))
- return d->callmap[any](op);
+ return d->callmap[any](op,eng);
return Exception(Exception::TypeMismatchError);
}
#include "dptr.h"
namespace ELAM {
+class Engine;
/** \brief pointer to a function wrapping an unary operator
\param op the operand to be worked on
+\param engine the engine calling the operator
\returns the result of the operation*/
-typedef QVariant (*UnaryOperatorCall)(const QVariant&op);
+typedef QVariant (*UnaryOperatorCall)(const QVariant&op,Engine&engine);
/** \brief Wraps a particular unary operator.
QList<int> getTypeIds()const;
///calls the callback function associated with the type of the argument, throws an exception if there is no callback
- QVariant execute(const QVariant&)const;
+ QVariant execute(const QVariant&,Engine&)const;
///true if this operator has no callbacks
bool isNull()const;
}
-static QVariant mycount(const QList<QVariant>&args)
+static QVariant mycount(const QList<QVariant>&args,Engine&)
{
return (qlonglong)args.size();
}
-static QVariant mysum(const QList<QVariant>&args)
+static QVariant mysum(const QList<QVariant>&args,Engine&)
{
qlonglong r=0;
for(int i=0;i<args.size();i++)