removed ELAMValue class (replaced by plain QVariant)
authorkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Fri, 12 Nov 2010 08:52:16 +0000 (08:52 +0000)
committerkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Fri, 12 Nov 2010 08:52:16 +0000 (08:52 +0000)
better draft of engine interface

git-svn-id: https://silmor.de/svn/softmagic/elam/trunk@623 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33

src/elam.pro
src/elamengine.cpp [new file with mode: 0644]
src/elamengine.h
src/elamvalue.cpp
src/elamvalue.h

index f0224c1..69c113f 100644 (file)
@@ -15,7 +15,8 @@ HEADERS += \
        elamvalue.h
 
 SOURCES += \
-       elamvalue.cpp
+       elamvalue.cpp \
+       elamengine.cpp
 
 INCLUDEPATH += .
 DEPENDPATH += .
diff --git a/src/elamengine.cpp b/src/elamengine.cpp
new file mode 100644 (file)
index 0000000..09dac3c
--- /dev/null
@@ -0,0 +1,145 @@
+// ELAM engine definition implementation
+//
+// (c) Konrad Rosenbaum, 2010
+// protected under the GNU LGPL v3 or at your option any newer
+
+#include "elamengine.h"
+#include "elamvalue.h"
+
+ELAMEngine::ELAMEngine(QObject* parent): QObject(parent)
+{
+
+}
+
+QVariant ELAMEngine::evaluate(QString ex)
+{
+       return evaluate(parseExpression(ex));
+}
+
+QVariant ELAMEngine::evaluate(ELAMExpression ex)
+{
+       //TODO: implement
+       return QVariant();
+}
+
+ELAMExpression ELAMEngine::parseExpression(QString )
+{
+       //TODO: implement parser
+       return ELAMExpression();
+}
+
+/////////////////////////////////////////////////////////////////
+// Unary Operator
+
+class ELAMUnaryOperator::Private
+{
+       public:
+               //memory management
+               int ctr;
+               Private(){ctr=1;}
+               void detach(){ctr--;if(ctr<=0)delete this;}
+               void attach(){ctr++;}
+               //callback mapping
+               QMap<int,ELAMUnaryOperatorCall>callmap;
+};
+
+ELAMUnaryOperator::ELAMUnaryOperator(const ELAMUnaryOperator& op)
+{
+       d=0;
+       operator=(op);
+}
+
+ELAMUnaryOperator::ELAMUnaryOperator()
+{
+       d=new Private();
+}
+
+ELAMUnaryOperator::~ELAMUnaryOperator()
+{
+       if(d)d->detach();
+       d=0;
+}
+
+
+ELAMUnaryOperator& ELAMUnaryOperator::operator=(const ELAMUnaryOperator& op)
+{
+       if(d)d->detach();
+       d=op.d;
+       if(d)d->attach();
+       return *this;
+}
+
+QVariant ELAMUnaryOperator::execute(const QVariant& op) const
+{
+       if(d->callmap.size()==0)
+               return qVariantFromValue<ELAMException>(ELAMException(ELAMException::UnknownOperatorError));
+       //search for direct match
+       if(d->callmap.contains(op.type()))
+               return d->callmap[op.type()](op);
+       //search for fallback
+       int any=ELAMAnyType::metaTypeId();
+       if(d->callmap.contains(any))
+               return d->callmap[any](op);
+       return qVariantFromValue<ELAMException>(ELAMException(ELAMException::TypeMismatchError));
+}
+
+QList< int > ELAMUnaryOperator::getTypeIds() const
+{
+       return d->callmap.keys();
+}
+
+QStringList ELAMUnaryOperator::getTypeNames() const
+{
+       QStringList ret;
+       QList<int>ti=d->callmap.keys();
+       for(int i=0;i<ti.size();i++)
+               ret<<QVariant::typeToName((QVariant::Type)ti[i]);
+       return ret;
+}
+
+ELAMUnaryOperatorCall ELAMUnaryOperator::getCallback(QString type) const
+{
+       return getCallback(QVariant::nameToType(type.toAscii().data()));
+}
+
+ELAMUnaryOperatorCall ELAMUnaryOperator::getCallback(int type) const
+{
+       if(d->callmap.contains(type))
+               return d->callmap[type];
+       if(d->callmap.contains(ELAMAnyType::metaTypeId()))
+               return d->callmap[ELAMAnyType::metaTypeId()];
+       return 0;
+}
+
+void ELAMUnaryOperator::setCallback(ELAMUnaryOperatorCall callback, int type)
+{
+       if(type==QVariant::Invalid)return;
+       if(callback==0){
+               d->callmap.remove(type);
+               return;
+       }
+       d->callmap.insert(type,callback);
+}
+
+void ELAMUnaryOperator::setCallback(ELAMUnaryOperatorCall callback, QString type)
+{
+       setCallback(callback,QVariant::nameToType(type.toAscii().data()));
+}
+
+void ELAMUnaryOperator::removeCallback(ELAMUnaryOperatorCall cb)
+{
+       if(cb==0)return;
+       QList<int>k=d->callmap.keys(cb);
+       for(int i=0;i<k.size();i++)
+               d->callmap.remove(k[i]);
+}
+
+void ELAMUnaryOperator::removeCallback(QString t)
+{
+       removeCallback(QVariant::nameToType(t.toAscii().data()));
+}
+
+void ELAMUnaryOperator::removeCallback(int t)
+{
+       d->callmap.remove(t);
+}
index 75be1cd..3bc054c 100644 (file)
@@ -6,20 +6,94 @@
 #ifndef ELAM_ENGINE_H
 #define ELAM_ENGINE_H
 
-#include <QString>
+#include <QStringList>
 #include <QObject>
+#include <QVariant>
 
 #include "elamexpression.h"
 
+/**pointer to a function wrapping an unary operator
+\param op the operand to be worked on
+\returns the result of the operation*/
+typedef QVariant (*ELAMUnaryOperatorCall)(const QVariant&op);
+
+class ELAMUnaryOperator
+{
+       public:
+               ELAMUnaryOperator(const ELAMUnaryOperator&);
+               ELAMUnaryOperator();
+               ~ELAMUnaryOperator();
+               
+               ELAMUnaryOperator& operator=(const ELAMUnaryOperator&);
+
+               /**sets a callback function for the operator and a specific typ
+               \param callback the function to call, if it is null the type is deleted from this operators type list
+               \param type the type of variable to work on, this must be a type registered with QVariant, if this type is already known to the operator its callback is replaced
+               */
+               void setCallback(ELAMUnaryOperatorCall callback,QString type);
+               /**sets a callback function for the operator and a specific typ
+               \param callback the function to call, if it is null the type is deleted from this operators type list
+               \param type the type of variable to work on, this must be a type registered with QVariant, if this type is already known to the operator its callback is replaced
+               */
+               void setCallback(ELAMUnaryOperatorCall callback,int type);
+               /**returns the callback function attached to the type or NULL if there is none*/
+               ELAMUnaryOperatorCall getCallback(QString type)const;
+               /**returns the callback function attached to the type or NULL if there is none*/
+               ELAMUnaryOperatorCall getCallback(int type)const;
+               
+               /**removes all types attached to this callback from the operator*/
+               void removeCallback(ELAMUnaryOperatorCall);
+               ///removes the type from this operators list
+               void removeCallback(QString);
+               ///removes the type from this operators list
+               void removeCallback(int);
+               
+               ///returns all type names that have a valid callback in this operator
+               QStringList getTypeNames()const;
+               ///returns all type IDs that have a valid callback in this 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;
+       private:
+               class Private;
+               Private *d;
+};
+
+/**pointer to a function wrapping a binary operator
+\param op1 the left operand
+\param op2 the right operand
+\returns the result of the operation*/
+typedef QVariant (*ELAMBinaryOperatorCall)(const QVariant&op1,const QVariant&op2);
+
+/**pointer to a function wrapping a mathematical function
+\param args the list of arguments
+\returns the result of the function*/
+typedef QVariant (*ELAMFunction)(const QList<QVariant>&args);
+
+
+/**The calculation engine of ELAM.
+
+Instances of this class can be configured to represent a specific system of functions and operators.
+
+Methods of this class are used to evaluate expressions into final values.
+*/
 class ELAMEngine:public QObject
 {
        Q_OBJECT
        public:
+               ///instantiates an engine object
                ELAMEngine(QObject*parent=0);
+               
        public slots:
+               ///simply parses an expression string into an ELAM object
                ELAMExpression parseExpression(QString);
-               ELAMValue evaluate(QString);
-               ELAMValue evaluate(ELAMExpression);
+               ///parses and evaluates an expression string into a final value
+               QVariant evaluate(QString);
+               ///evaluates a parsed expression into a final value
+               QVariant evaluate(ELAMExpression);
+               
+               
        private:
                class Private;
                Private *d;
index 5d4b9bb..8322ac2 100644 (file)
@@ -5,91 +5,36 @@
 
 #include "elamvalue.h"
 
-ELAMValue::ELAMValue()
+ELAMException::ELAMException()
 {
-       m_exc=false;
-       m_exline=m_excol=-1;
+       mline=mcol=-1;
 }
-
-ELAMValue::ELAMValue(long long l)
-{
-       m_exc=false;
-       m_exline=m_excol=-1;
-       m_val=l;
-}
-
-ELAMValue::ELAMValue(double d)
-{
-       m_exc=false;
-       m_exline=m_excol=-1;
-       m_val=d;
-}
-
-ELAMValue::ELAMValue(QString s)
+ELAMException::ELAMException(const ELAMException& e)
 {
-       m_exc=false;
-       m_exline=m_excol=-1;
-       m_val=s;
+       operator=(e);
 }
-
-ELAMValue::ELAMValue(QVariant v)
+ELAMException::ELAMException(ErrorType tp,QString errText, int line, int column)
 {
-       m_exc=false;
-       m_exline=m_excol=-1;
-       //TODO: registered type?
-       m_val=v;
+       mtype=tp;
+       merr=errText;
+       mline=line;
+       mcol=column;
 }
-
-ELAMValue& ELAMValue::operator=(const ELAMValue&e)
+static int ELAMException_metaid=qRegisterMetaType<ELAMException>();
+int ELAMException::metaTypeId()
 {
-       m_exc=e.m_exc;
-       m_exstr=e.m_exstr;
-       m_exline=e.m_exline;
-       m_excol=e.m_excol;
-       m_val=e.m_val;
-       return *this;
+       return ELAMException_metaid;
 }
-
-ELAMValue& ELAMValue::operator=(long long v)
+ELAMException& ELAMException::operator=(const ELAMException& e)
 {
-       m_exc=false;m_excol=m_exline=-1;m_exstr=QString();
-       m_val=v;
+       merr=e.merr;
+       mline=e.mline;
+       mcol=e.mcol;
        return *this;
 }
 
-ELAMValue& ELAMValue::operator=(int v)
-{
-       m_exc=false;m_excol=m_exline=-1;m_exstr=QString();
-       m_val=v;
-       return *this;
-}
-
-ELAMValue& ELAMValue::operator=(const QString&v)
-{
-       m_exc=false;m_excol=m_exline=-1;m_exstr=QString();
-       m_val=v;
-       return *this;
-}
-
-ELAMValue& ELAMValue::operator=(const QVariant&v)
-{
-       m_exc=false;m_excol=m_exline=-1;m_exstr=QString();
-       m_val=v;
-       return *this;
-}
-
-
-void ELAMValue::setException(QString s,int l,int c)
-{
-       m_exc=true;
-       m_exline=l;m_excol=c;
-       m_exstr=s;
-}
-
-QPair<int,int> ELAMValue::exceptionPos()const
+static int ELAMAnyType_metaid=qRegisterMetaType<ELAMAnyType>();
+int ELAMAnyType::metaTypeId()
 {
-       if(m_exc)
-               return QPair<int,int>(m_exline,m_excol);
-       else
-               return QPair<int,int>(-1,-1);
+       return ELAMAnyType_metaid;
 }
index f30f7c9..a95cafe 100644 (file)
 #include <QString>
 #include <QPair>
 
-class ELAMValue
+/**Objects of this class represent an exception in the evaluation of an ELAM expression.*/
+class ELAMException
 {
        public:
-               ELAMValue();
-               ELAMValue(long long);
-               ELAMValue(double);
-               ELAMValue(QString);
-               ELAMValue(QVariant);
-               ELAMValue& operator=(const ELAMValue&);
-               ELAMValue& operator=(long long);
-               ELAMValue& operator=(int);
-               ELAMValue& operator=(const QString&);
-               ELAMValue& operator=(const QVariant&);
+               enum ErrorType{
+                       NoError=0,
+                       ParserError,
+                       UnknownOperatorError,
+                       UnknownFunctionError,
+                       TypeMismatchError,
+               };
                
-               bool isNull()const{return m_val.isNull();}
+               ELAMException();
+               ELAMException(const ELAMException&);
+               ELAMException(ErrorType type,QString errorText=QString(),int line=-1,int column=-1);
                
-               void setException(QString,int,int);
+               ELAMException& operator=(const ELAMException&);
                
-               bool hasException()const{return m_exc;}
-               QString exceptionString()const{return m_exc?m_exstr:QString();}
-               QPair<int,int> exceptionPos()const;
+               QString errorText()const{return merr;}
+               int errorLine()const{return mline;}
+               int errorColumn()const{return mcol;}
+               QPair<int,int> errorPos()const{return QPair<int,int>(mline,mcol);}
                
-               QVariant toVariant()const{return m_val;}
-               long long toInt()const{return m_val.toInt();}
-               QString toString()const{return m_val.toString();}
+               static int metaTypeId();
                
        private:
-               QVariant m_val;
-               bool m_exc;
-               QString m_exstr;
-               int m_exline,m_excol;
+               ErrorType mtype;
+               QString merr;
+               int mline,mcol;
 };
+Q_DECLARE_METATYPE(ELAMException);
+
+/**this type is not actually used, its ID is used as a fallback to tell operators, functions and engines that any supported type can be used*/
+class ELAMAnyType
+{
+       public:
+               ///returns the meta type ID of the ANY type
+               static int metaTypeId();
+};
+Q_DECLARE_METATYPE(ELAMAnyType);
 
 #endif