From: konrad Date: Mon, 27 Dec 2010 11:12:07 +0000 (+0000) Subject: put context to functions and operators X-Git-Url: http://git.silmor.de/gitweb/?a=commitdiff_plain;h=eeb98c11253a9d4026ed8d19246ecd8ae544449e;p=web%2Fkonrad%2Felam.git put context to functions and operators git-svn-id: https://silmor.de/svn/softmagic/elam/trunk@683 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33 --- diff --git a/src/elambinary.cpp b/src/elambinary.cpp index 8fc47b3..7a21280 100644 --- a/src/elambinary.cpp +++ b/src/elambinary.cpp @@ -40,7 +40,7 @@ BinaryOperator::~BinaryOperator() { } -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 QPairk(op1.userType(),op2.userType()); @@ -57,7 +57,7 @@ QVariant BinaryOperator::execute ( const QVariant&op1,const QVariant&op2 ) const 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 diff --git a/src/elambinary.h b/src/elambinary.h index ccbe70a..6ab4f6d 100644 --- a/src/elambinary.h +++ b/src/elambinary.h @@ -13,12 +13,14 @@ #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. @@ -62,7 +64,7 @@ class BinaryOperator QList > 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; diff --git a/src/elamboolengine.cpp b/src/elamboolengine.cpp index 7813106..02f5fd2 100644 --- a/src/elamboolengine.cpp +++ b/src/elamboolengine.cpp @@ -16,7 +16,7 @@ BoolEngine::BoolEngine() } -static QVariant boolFunc(const QList&lf) +static QVariant boolFunc(const QList&lf,Engine&) { if(lf.size()!=1) return Exception(Exception::ArgumentListError, "expecting exactly one argument"); @@ -26,26 +26,26 @@ static QVariant boolFunc(const QList&lf) } //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) { @@ -87,7 +87,7 @@ void BoolEngine::configureBoolEngine(Engine&eng) eng.binaryOperator("^^",25).setCallback(boolXor,bid,bid); } -static QVariant ifFunc(const QList&lf) +static QVariant ifFunc(const QList&lf,Engine&) { if(lf.size()<2 || lf.size()>3) return Exception(Exception::ArgumentListError, "expecting 2 or 3 arguments"); @@ -100,28 +100,28 @@ static QVariant ifFunc(const QList&lf) return QVariant(); } -static QVariant isNullFunc(const QList&lf) +static QVariant isNullFunc(const QList&lf,Engine&) { if(lf.size()!=1) return Exception(Exception::ArgumentListError, "expecting exactly one argument"); return lf[0].isNull(); } -static QVariant isExceptionFunc(const QList&lf) +static QVariant isExceptionFunc(const QList&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&lf) +static QVariant isExceptionOrNullFunc(const QList&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&lf) +static QVariant catchFunc(const QList&lf,Engine&) { if(lf.size()<1||lf.size()>3) return Exception(Exception::ArgumentListError, "expecting 1-3 arguments"); diff --git a/src/elamengine.cpp b/src/elamengine.cpp index 501a4a1..da3cbbf 100644 --- a/src/elamengine.cpp +++ b/src/elamengine.cpp @@ -163,8 +163,8 @@ QVariant Engine::getVariable(QString n) const 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(); } @@ -180,7 +180,7 @@ bool Engine::hasVariable(QString n) const 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) @@ -195,15 +195,15 @@ void Engine::removeVariable(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; } @@ -211,7 +211,7 @@ bool Engine::setConstant(QString n, QVariant v) 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; @@ -232,8 +232,8 @@ bool Engine::setFunction(QString n, ELAM::Function p) { 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; } @@ -406,7 +406,7 @@ QVariant Engine::autoCast(const QVariant& v)const } //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 diff --git a/src/elamengine.h b/src/elamengine.h index e5774b9..196dcc5 100644 --- a/src/elamengine.h +++ b/src/elamengine.h @@ -20,16 +20,19 @@ 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&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&args,Engine&engine); -class Engine; /**wraps the parser routine for a literal \param expr the original expression string @@ -45,8 +48,9 @@ typedef QPair (*LiteralParser)(const QString&expr,Engine&engin /**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 . @@ -63,11 +67,12 @@ class Engine:public QObject 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; @@ -117,9 +122,9 @@ class Engine:public QObject 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 @@ -129,11 +134,12 @@ class Engine:public QObject 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 @@ -141,7 +147,7 @@ class Engine:public QObject - 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: @@ -149,14 +155,15 @@ class Engine:public QObject - 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. diff --git a/src/elamexpression.cpp b/src/elamexpression.cpp index 799ad8e..e2d0169 100644 --- a/src/elamexpression.cpp +++ b/src/elamexpression.cpp @@ -449,7 +449,7 @@ QVariant Expression::evalBinary() //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()) @@ -487,7 +487,7 @@ QVariant Expression::evalFunction() for(int i=0;isubexpr.size();i++) args<parent->autoCast(d->subexpr[i].evaluate()); //execute - return func(args); + return func(args,*(d->parent)); } QVariant Expression::evalUnary() @@ -504,7 +504,7 @@ QVariant Expression::evalUnary() //get operator UnaryOperator unop=d->parent->unaryOperator(un); //perform operation - return unop.execute(sub); + return unop.execute(sub,*(d->parent)); } diff --git a/src/elamfloatengine.cpp b/src/elamfloatengine.cpp index b0ffb66..a09554a 100644 --- a/src/elamfloatengine.cpp +++ b/src/elamfloatengine.cpp @@ -66,27 +66,27 @@ static QPair floatLiteralParser2(const QString&expr,Engine&eng else return QPair(); } -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) @@ -94,7 +94,7 @@ static QVariant floatDiv(const QVariant &o1,const QVariant &o2) return o1.toDouble()/d2; } -static QVariant floatFunc(const QList&lf) +static QVariant floatFunc(const QList&lf,Engine&) { if(lf.size()!=1) return Exception(Exception::ArgumentListError, "expecting exactly one argument"); @@ -112,7 +112,7 @@ int FloatEngine::floatLowParserPrio() 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) { diff --git a/src/elamintengine.cpp b/src/elamintengine.cpp index 41144a0..26e6ff3 100644 --- a/src/elamintengine.cpp +++ b/src/elamintengine.cpp @@ -35,7 +35,7 @@ static QPair IntLiteralParser(const QString&expr,Engine&engine else return QPair(); } -static QVariant intFunc(const QList&lf) +static QVariant intFunc(const QList&lf,Engine&) { if(lf.size()!=1) return Exception(Exception::ArgumentListError, "expecting exactly one argument"); @@ -45,38 +45,38 @@ static QVariant intFunc(const QList&lf) } //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) @@ -85,19 +85,19 @@ static QVariant intMod(const QVariant&o1,const QVariant&o2) } //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(); } @@ -108,7 +108,7 @@ int IntEngine::intParserPrio() 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) { diff --git a/src/elamstringengine.cpp b/src/elamstringengine.cpp index 3b7bce9..8ec10c4 100644 --- a/src/elamstringengine.cpp +++ b/src/elamstringengine.cpp @@ -112,7 +112,7 @@ static QPair strLiteralParser(const QString&expr,Engine&engine return QPair(ls,r); } -static QVariant strFunc(const QList&lf) +static QVariant strFunc(const QList&lf,Engine&) { if(lf.size()!=1) return Exception(Exception::ArgumentListError, "expecting exactly one argument"); @@ -121,7 +121,7 @@ static QVariant strFunc(const QList&lf) return lf[0].toString(); } -static QVariant strlenFunc(const QList&lf) +static QVariant strlenFunc(const QList&lf,Engine&) { if(lf.size()!=1) return Exception(Exception::ArgumentListError, "expecting exactly one argument"); @@ -130,7 +130,7 @@ static QVariant strlenFunc(const QList&lf) return (qlonglong)lf[0].toString().size(); } -static QVariant concatFunc(const QList&lf) +static QVariant concatFunc(const QList&lf,Engine&) { QString ret; for(int i=0;i&lf) 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(); } @@ -148,7 +148,7 @@ int StringEngine::stringParserPrio() 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) { diff --git a/src/elamunary.cpp b/src/elamunary.cpp index 6556baf..3014de7 100644 --- a/src/elamunary.cpp +++ b/src/elamunary.cpp @@ -42,17 +42,17 @@ UnaryOperator::~UnaryOperator() } -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); } diff --git a/src/elamunary.h b/src/elamunary.h index d331dbc..1e8b1a2 100644 --- a/src/elamunary.h +++ b/src/elamunary.h @@ -13,11 +13,13 @@ #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. @@ -66,7 +68,7 @@ class UnaryOperator QList 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; diff --git a/tests/eval/eval.cpp b/tests/eval/eval.cpp index da3adaf..afdf8df 100644 --- a/tests/eval/eval.cpp +++ b/tests/eval/eval.cpp @@ -38,11 +38,11 @@ void ElamTest::evaltest() } -static QVariant mycount(const QList&args) +static QVariant mycount(const QList&args,Engine&) { return (qlonglong)args.size(); } -static QVariant mysum(const QList&args) +static QVariant mysum(const QList&args,Engine&) { qlonglong r=0; for(int i=0;i