put context to functions and operators
authorkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Mon, 27 Dec 2010 11:12:07 +0000 (11:12 +0000)
committerkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Mon, 27 Dec 2010 11:12:07 +0000 (11:12 +0000)
git-svn-id: https://silmor.de/svn/softmagic/elam/trunk@683 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33

12 files changed:
src/elambinary.cpp
src/elambinary.h
src/elamboolengine.cpp
src/elamengine.cpp
src/elamengine.h
src/elamexpression.cpp
src/elamfloatengine.cpp
src/elamintengine.cpp
src/elamstringengine.cpp
src/elamunary.cpp
src/elamunary.h
tests/eval/eval.cpp

index 8fc47b3..7a21280 100644 (file)
@@ -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
        QPair<int,int>k(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
index ccbe70a..6ab4f6d 100644 (file)
 #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<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;
index 7813106..02f5fd2 100644 (file)
@@ -16,7 +16,7 @@ BoolEngine::BoolEngine()
 }
 
 
-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");
@@ -26,26 +26,26 @@ static QVariant boolFunc(const QList<QVariant>&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<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");
@@ -100,28 +100,28 @@ static QVariant ifFunc(const QList<QVariant>&lf)
                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");
index 501a4a1..da3cbbf 100644 (file)
@@ -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
index e5774b9..196dcc5 100644 (file)
 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
@@ -45,8 +48,9 @@ typedef QPair<QString,QVariant> (*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.
index 799ad8e..e2d0169 100644 (file)
@@ -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;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()
@@ -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));
 }
 
 
index b0ffb66..a09554a 100644 (file)
@@ -66,27 +66,27 @@ static QPair<QString,QVariant> floatLiteralParser2(const QString&expr,Engine&eng
        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)
@@ -94,7 +94,7 @@ static QVariant floatDiv(const QVariant &o1,const QVariant &o2)
        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");
@@ -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)
 {
index 41144a0..26e6ff3 100644 (file)
@@ -35,7 +35,7 @@ static QPair<QString,QVariant> IntLiteralParser(const QString&expr,Engine&engine
        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");
@@ -45,38 +45,38 @@ static QVariant intFunc(const QList<QVariant>&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)
 {
index 3b7bce9..8ec10c4 100644 (file)
@@ -112,7 +112,7 @@ static QPair<QString,QVariant> strLiteralParser(const QString&expr,Engine&engine
        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");
@@ -121,7 +121,7 @@ static QVariant strFunc(const QList<QVariant>&lf)
        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");
@@ -130,7 +130,7 @@ static QVariant strlenFunc(const QList<QVariant>&lf)
        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++)
@@ -138,7 +138,7 @@ static QVariant concatFunc(const QList<QVariant>&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)
 {
index 6556baf..3014de7 100644 (file)
@@ -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);
 }
 
index d331dbc..1e8b1a2 100644 (file)
 #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<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;
index da3adaf..afdf8df 100644 (file)
@@ -38,11 +38,11 @@ void ElamTest::evaltest()
        
 }
 
-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++)