add reflection abilities
authorKonrad Rosenbaum <konrad@silmor.de>
Fri, 23 Mar 2012 09:00:39 +0000 (10:00 +0100)
committerKonrad Rosenbaum <konrad@silmor.de>
Fri, 23 Mar 2012 09:00:39 +0000 (10:00 +0100)
doc/library.html
src/elamengine.cpp
src/elamengine.h
src/elamintengine.cpp
src/elamvalue.cpp
src/elamvalue.h

index 740bf3f..46db21e 100644 (file)
@@ -181,6 +181,18 @@ Examples include: "hello World!", 'hello World!', 'line\r\nbreak'.<p>
 
 Use the convenience type ELAM::StringEngine or its static method configureStringEngine to get this functionality.
 
+<h3>Reflection Library</h3>
+
+The reflection library defines some type inquiry functions:
+<table frame="1" border="1">
+<tr><td><b>Function</b></td><td><b>Description</b></td></tr>
+<tr><td>typeid(any)</td><td>returns the numeric type ID of the argument, see QVariant::type() for details</td><tr>
+<tr><td>typename(any)</td><td>returns the name of the type of the argument</td></tr>
+<tr><td>showexception(expression, ...)</td><td>takes any number of arguments and returns a string showing either the type of each expression or the details of the exception it threw</td></tr>
+</table><p>
+
+Use the static method ELAM::Engine::configureReflection to get this functionality.
+
 
 <h1>Extending The ELAM Libray</h1>
 
index 824637a..569248e 100644 (file)
@@ -438,5 +438,43 @@ QStringList Engine::variableNames() const
        return d->vars.keys();
 }
 
+static QVariant reflectTypeId(const QList<QVariant>&args,Engine&)
+{
+       if(args.size()!=1)
+               return QVariant::fromValue(Exception(Exception::ArgumentListError,"expecting one argument"));
+       return (int)args[0].type();
+}
+
+static QVariant reflectTypeName(const QList<QVariant>&args,Engine&)
+{
+       if(args.size()!=1)
+               return QVariant::fromValue(Exception(Exception::ArgumentListError,"expecting one argument"));
+       return QString(args[0].typeName());
+}
+
+static QVariant reflectException(const QList<QVariant>&args,Engine&)
+{
+       QString ret;
+       for(auto arg:args){
+               if(ret.size())ret+="; ";
+               if(arg.type()==Exception::metaTypeId()){
+                       Exception e=arg.value<Exception>();
+                       ret+=QString("Exception(type=%1, position=%2, message='%3')")
+                               .arg(e.errorTypeName())
+                               .arg((QString)e.errorPos())
+                               .arg(e.errorText());
+               }
+       }
+       return ret;
+}
+
+void Engine::configureReflection(Engine& e)
+{
+       e.setFunction("typeid",reflectTypeId);
+       e.setFunction("typename",reflectTypeName);
+       e.setFunction("showexception",reflectException);
+}
+
+
 //end of namespace
 };
\ No newline at end of file
index c849338..0912bb2 100644 (file)
@@ -92,6 +92,9 @@ class Engine:public QObject
                ///instantiates an engine object
                explicit Engine(QObject*parent=0);
                
+               ///register reflection functions
+               static void configureReflection(Engine&);
+               
                ///true if the named variable exists in this engine
                Q_INVOKABLE virtual bool hasVariable(QString)const;
                ///true if the named constant exists in this engine
index f4e329e..b301066 100644 (file)
@@ -47,7 +47,8 @@ static QVariant intFunc(const QList<QVariant>&lf,Engine&)
 //unary
 static QVariant intPlus(const QVariant&o,Engine&)
 {
-       return o;
+       //force to int
+       return o.toLongLong();
 }
 static QVariant intMinus(const QVariant&o,Engine&)
 {
@@ -139,7 +140,10 @@ void IntEngine::configureIntEngine(ELAM::Engine& eng)
 {
        int iid=QVariant::LongLong;
        eng.setLiteralParser(IntLiteralParser,"0123456789",intParserPrio());
-       eng.setAutoCast(iid, QList<int>()<<QVariant::Int<<QVariant::UInt<<QVariant::ULongLong, intCast, 40);
+       eng.setAutoCast(iid, 
+                       QList<int>()<<QVariant::Int<<QVariant::UInt
+                               <<QVariant::ULongLong<<QVariant::LongLong, 
+                       intCast, 40);
        eng.setAutoCast(iid, QList<int>()<<QVariant::Double, intCast, 30);
        //cast
        eng.setFunction("int",intFunc);
index 2b88537..5f8febd 100644 (file)
@@ -47,6 +47,29 @@ Exception& Exception::operator=(const Exception& e)
        return *this;
 }
 
+QString Exception::errorTypeName() const
+{
+       switch(mtype){
+               case NoError:return "no error";
+               ///error while parsing the expression
+               case ParserError:return "parser error";
+               ///the operator is not known
+               case UnknownOperatorError:return "unknown operator";
+               ///the function is not known
+               case UnknownFunctionError:return "unknown function";
+               ///unknown variable or constant
+               case UnknownValueError:return "unknown variable or constant";
+               ///the operator or function is known, but the type of one of the arguments is not supported
+               case TypeMismatchError:return "type mismatch";
+               ///the amount of arguments to a function is wrong or the syntax of arguments
+               case ArgumentListError:return "invalid argument list";
+               ///the operation itself failed, e.g. division by zero
+               case OperationError:return "invalid operation";
+               default:return "unknown error";
+       }
+}
+
+
 static int AnyType_metaid=qRegisterMetaType<AnyType>();
 int AnyType::metaTypeId()
 {
index f6a1fa9..4a8ccfc 100644 (file)
@@ -49,6 +49,9 @@ class Position
                inline operator QPair<int,int>()const{return QPair<int,int>(mline,mcol);}
                ///transparently converts to a QPoint, with x=column and y=line
                inline operator QPoint()const{return QPoint(mcol,mline);}
+               ///converts to a human readable QString
+               explicit inline operator QString()const
+               {return QString("line=%1, column=%2").arg(mline).arg(mcol);}
        private:
                int mline,mcol;
 };
@@ -100,6 +103,8 @@ class Exception
                QString errorText()const{return merr;}
                ///type of error represented by the exception
                ErrorType errorType()const{return mtype;}
+               ///returns a human readable error type name of this exception
+               QString errorTypeName()const;
                ///the position in the original expression where the error originated
                Position errorPos()const{return mpos;}
                ///the position in the original expression where the error originated