File indexing completed on 2024-04-28 03:40:41

0001 /*************************************************************************************
0002  *  Copyright (C) 2007 by Aleix Pol <aleixpol@kde.org>                               *
0003  *                                                                                   *
0004  *  This program is free software; you can redistribute it and/or                    *
0005  *  modify it under the terms of the GNU General Public License                      *
0006  *  as published by the Free Software Foundation; either version 2                   *
0007  *  of the License, or (at your option) any later version.                           *
0008  *                                                                                   *
0009  *  This program is distributed in the hope that it will be useful,                  *
0010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of                   *
0011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                    *
0012  *  GNU General Public License for more details.                                     *
0013  *                                                                                   *
0014  *  You should have received a copy of the GNU General Public License                *
0015  *  along with this program; if not, write to the Free Software                      *
0016  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA   *
0017  *************************************************************************************/
0018 #include "expression.h"
0019 
0020 #include <QDomElement>
0021 #include <QCoreApplication>
0022 
0023 #include "explexer.h"
0024 #include "expressionparser.h"
0025 #include "container.h"
0026 #include "value.h"
0027 #include "vector.h"
0028 #include "variable.h"
0029 #include "stringexpressionwriter.h"
0030 #include "htmlexpressionwriter.h"
0031 #include "mathmlexpressionwriter.h"
0032 #include "mathmlpresentationexpressionwriter.h"
0033 #include "list.h"
0034 #include "analitzautils.h"
0035 #include "apply.h"
0036 #include "customobject.h"
0037 
0038 #include "matrix.h"
0039 
0040 using namespace Analitza;
0041 
0042 class Expression::ExpressionPrivate : public QSharedData
0043 {
0044 public:
0045     ExpressionPrivate(Object* t) : m_tree(t) {}
0046     
0047     bool canAdd(const Object* where, const Object* branch);
0048     bool check(const Container* c);
0049     bool check(const Apply* c);
0050     
0051     Object* branch(const QDomElement& elem);
0052     
0053     template <class T, class Tcontained = Object>
0054     T* addElements(T* v, const QDomElement* elem)
0055     {
0056         QDomNode n = elem->firstChild();
0057         while(!n.isNull()) {
0058             if(n.isElement()) {
0059                 Object* ob= branch(n.toElement()); //TODO: We should do that better
0060                 
0061                 if(ob && canAdd(v, ob)) {
0062                     v->appendBranch(static_cast<Tcontained*>(ob));
0063                 } else {
0064 //                     delete ob;
0065                     delete v;
0066                     return nullptr;
0067                 }
0068             }
0069             n = n.nextSibling();
0070         }
0071         return v;
0072     }
0073     static List* listFromString(const QString& text);
0074     
0075     Object* m_tree;
0076     QStringList m_err;
0077 };
0078 
0079 Expression::Expression()
0080     : d(new ExpressionPrivate(nullptr))
0081 {}
0082 
0083 Expression::Expression(Object * o)
0084     : d(new ExpressionPrivate(o))
0085 {}
0086 
0087 Expression::Expression(const Cn & e)
0088     : d(new ExpressionPrivate(nullptr))
0089 {
0090     d->m_tree = new Cn(e);
0091 }
0092 
0093 Expression::Expression(const Expression & e)
0094     : d(new ExpressionPrivate(nullptr))
0095 {
0096     d->m_err=e.d->m_err;
0097     if(e.isCorrect() && e.d->m_tree)
0098         d->m_tree = e.d->m_tree->copy();
0099 }
0100 
0101 Expression::Expression(const QString & exp, bool mathml)
0102     : d(new ExpressionPrivate(nullptr))
0103 {
0104     if(mathml)
0105         setMathML(exp);
0106     else
0107         setText(exp);
0108 }
0109 
0110 Expression::~Expression()
0111 {
0112     Q_ASSERT(d);
0113     delete d->m_tree;
0114 }
0115 
0116 Expression Expression::operator=(const Expression & e)
0117 {
0118     if(this != &e) {
0119         delete d->m_tree;
0120         
0121         if(e.d->m_tree)
0122             d->m_tree = e.d->m_tree->copy();
0123         else
0124             d->m_tree=nullptr;
0125         
0126         d->m_err = e.d->m_err;
0127     }
0128     return *this;
0129 }
0130 
0131 bool Expression::setText(const QString & exp)
0132 {
0133     if(exp.isEmpty()) {
0134         delete d->m_tree;
0135         d->m_tree = nullptr;
0136         return true;
0137     }
0138     d->m_err.clear();
0139     ExpLexer lex(exp);
0140     ExpressionParser parser;
0141     m_comments = parser.comments();
0142     bool corr=parser.parse(&lex);
0143     
0144     if(corr)
0145         setMathML(parser.mathML());
0146     else
0147         d->m_err << parser.error();
0148     
0149     return corr;
0150 }
0151 
0152 bool Expression::ExpressionPrivate::check(const Apply* c)
0153 {
0154     bool ret=true;
0155     Operator op=c->firstOperator();
0156     Operator::OperatorType opt=op.operatorType();
0157     int cnt=c->countValues();
0158     
0159     if(((op.nparams()<0 && cnt<=1) || (op.nparams()>-1 && cnt!=op.nparams())) && (opt!=Operator::minus || cnt==0) && opt!=Operator::function)
0160     {
0161         if(op.nparams()<0)
0162             m_err << QCoreApplication::tr("<em>%1</em> needs at least 2 parameters").arg(op.toString());
0163         else
0164             m_err << QCoreApplication::tr("<em>%1</em> requires %2 parameters")
0165                                             .arg(op.toString())
0166                                             .arg(op.nparams());
0167         ret=false;
0168     }
0169     
0170     if(op.isBounded() && !c->hasBVars()) {
0171         m_err << QCoreApplication::tr("Missing boundary for '%1'").arg(op.toString());
0172     } else if(!op.isBounded() && c->hasBVars()) {
0173         m_err << QCoreApplication::tr("Unexpected bounding for '%1'").arg(op.toString());
0174     }
0175     
0176     if(op.isBounded() && op!=Operator::diff) {
0177         if(!(c->ulimit() && c->dlimit()) && !c->domain()) {
0178             m_err << QCoreApplication::tr("<em>%1</em> missing bounds on '%2'").arg(c->bvarStrings().join(QStringLiteral(" ")), op.toString());
0179         }
0180     }
0181     
0182     return ret;
0183 }
0184 
0185 List* Expression::ExpressionPrivate::listFromString(const QString& text)
0186 {
0187     List* l = new List;
0188     for(int i=0; i<text.size(); ++i)
0189         l->appendBranch(new Cn(text[i]));
0190     return l;
0191 }
0192 
0193 bool Expression::ExpressionPrivate::check(const Container* c)
0194 {
0195     bool ret=true;
0196     
0197     switch(c->containerType()) {
0198         case Container::declare:
0199             if(c->m_params.size()!=2) {
0200                 m_err << QCoreApplication::tr("Wrong declare");
0201                 ret=false;
0202             }
0203             break;
0204         default:
0205             //should never do anything here,
0206             break;
0207     }
0208     
0209     if(c->isEmpty() && c->containerType()!=Container::math) {
0210         m_err << QCoreApplication::tr("Empty container: %1").arg(c->tagName());
0211         ret=false;
0212     }
0213     
0214     return ret;
0215 }
0216 
0217 bool Expression::ExpressionPrivate::canAdd(const Object* where, const Object* branch)
0218 {
0219     Q_ASSERT(where && branch);
0220     bool correct=true;
0221     
0222     if(branch->type()==Object::container) {
0223         const Container* cBranch=static_cast<const Container*>(branch);
0224         if(cBranch->containerType()==Container::piece || cBranch->containerType()==Container::otherwise) {
0225             bool isPiecewise=where->type()==Object::container
0226                 && static_cast<const Container*>(where)->containerType()==Container::piecewise;
0227             if(!isPiecewise) {
0228                 m_err << QCoreApplication::translate("there was a conditional outside a condition structure",
0229                                 "We can only have conditionals inside piecewise structures.");
0230                 correct=false;
0231             }
0232         } else if(cBranch->containerType()==Container::bvar && (where->isContainer() || where->isApply())) {
0233             //we don't want 2 bvar in the same element
0234             QStringList bvars;
0235             if(where->isContainer())
0236                 bvars=static_cast<const Container*>(where)->bvarStrings();
0237             else
0238                 bvars=static_cast<const Apply*>(where)->bvarStrings();
0239             
0240             const Ci* var= static_cast<const Ci*>(cBranch->m_params.first());
0241             
0242             if(bvars.contains(var->name())) {
0243                 correct=false;
0244                 m_err << QCoreApplication::tr("Cannot have two parameters with the same name like '%1'.").arg(var->name());
0245             }
0246         }
0247     }
0248     
0249     if(where->type()==Object::container) {
0250         const Container* cWhere=static_cast<const Container*>(where);
0251         
0252         if(cWhere->containerType()==Container::piecewise) {
0253             bool isCondition=false;
0254             if(branch->type()==Object::container) {
0255                 Container::ContainerType ct=static_cast<const Container*>(branch)->containerType();
0256                 isCondition=ct==Container::piece || ct==Container::otherwise;
0257                 
0258                 if(cWhere->extractType(Container::otherwise)) {
0259                     m_err << QCoreApplication::translate("this is an error message. otherwise is the else in a mathml condition",
0260                         "The <em>otherwise</em> parameter should be the last one");
0261                     correct=false;
0262                 }
0263                 
0264             }
0265             
0266             if(!isCondition) {
0267                 m_err << QCoreApplication::translate("there was an element that was not a conditional inside a condition",
0268                                     "%1 is not a proper condition inside the piecewise").arg(branch->toString());
0269                 correct=false;
0270             }
0271             
0272         } else if(cWhere->containerType()==Container::declare && cWhere->isEmpty() && branch->type()!=Object::variable) {
0273             m_err << QCoreApplication::tr("We can only declare variables");
0274             correct=false;
0275         }
0276         
0277         if(cWhere->containerType()==Container::bvar) {
0278             if(branch->type()!=Object::variable) {
0279                 m_err << QCoreApplication::tr("We can only have bounded variables");
0280                 correct=false;
0281             }
0282         }
0283     } else 
0284         if(where->type()==Object::matrix) {
0285             if(branch->type()==Object::matrixrow) {
0286                 const Matrix *matrix = static_cast<const Matrix*>(where);
0287                 const MatrixRow *matrixrow = static_cast<const MatrixRow*>(branch);
0288                 
0289                 if (matrixrow->size() == 0) {
0290                     m_err << QCoreApplication::tr("Do not want empty matrixrow elements");
0291                     correct=false;
0292                 }
0293                 
0294                 if (matrix->rowCount() != 0)
0295                     if (static_cast<MatrixRow*>(matrix->rows().at(0))->size() != matrixrow->size()) {
0296                         m_err << QCoreApplication::tr("All matrixrow elements must have the same size");
0297                         correct=false;
0298                     }
0299             } else {
0300                 m_err << QCoreApplication::tr("The matrix must contain only matrixrow elements");
0301                 correct=false;
0302             }
0303         }
0304     
0305     Q_ASSERT(correct || !m_err.isEmpty());
0306     
0307     return correct;
0308 }
0309 
0310 static void variableDepth(Object* o, int& next, const QMap<QString, int>& scope, const Object* parent=nullptr)
0311 {
0312     Q_ASSERT(o);
0313     switch(o->type()) {
0314         case Object::variable: {
0315             Ci *i = (Ci*) o;
0316             QMap<QString, int>::const_iterator it = scope.constFind(i->name());
0317             i->setBVarDepth(it==scope.constEnd() 
0318                             ? -1
0319                             : *it);
0320             
0321         }    break;
0322         case Object::vector: {
0323             Vector *v=(Vector*) o;
0324             for(Vector::const_iterator it=v->constBegin(); it!=v->constEnd(); ++it)
0325                 variableDepth(*it, next, scope);
0326         }    break;
0327         case Object::matrix: {
0328             Matrix *v=(Matrix*) o;
0329             for(Matrix::const_iterator it=v->constBegin(); it!=v->constEnd(); ++it)
0330                 variableDepth(*it, next, scope);
0331         }    break;
0332         case Object::matrixrow: {
0333             MatrixRow *v=(MatrixRow*) o;
0334             for(MatrixRow::const_iterator it=v->constBegin(); it!=v->constEnd(); ++it)
0335                 variableDepth(*it, next, scope);
0336         }    break;
0337         case Object::list: {
0338             List *v=(List*) o;
0339             for(List::const_iterator it=v->constBegin(); it!=v->constEnd(); ++it)
0340                 variableDepth(*it, next, scope);
0341             
0342         }    break;
0343         case Object::container: {
0344             const Container *c = (const Container*) o;
0345             
0346             QMap<QString, int> newScope=scope;
0347             
0348             Container::const_iterator it=c->m_params.constBegin(), itEnd=c->m_params.constEnd();
0349             if(c->containerType()==Container::declare) {
0350                 Ci* var = static_cast<Ci*>(*it);
0351                 ++it;
0352                 
0353                 if((*it)->isContainer() && static_cast<const Container*>(*it)->containerType()==Container::lambda) {
0354                     newScope.insert(var->name(), next);
0355                     var->setBVarDepth(next++);
0356                 }
0357             } else if(c->containerType()==Container::lambda &&
0358                 !(parent && parent->isContainer() && static_cast<const Container*>(parent)->containerType()==Container::declare)) {
0359                     ++next;
0360             }
0361             
0362             foreach(Ci* bvar, c->bvarCi()) {
0363                 newScope.insert(bvar->name(), next);
0364                 bvar->setBVarDepth(next++);
0365             }
0366             
0367             for(; it!=itEnd; ++it)
0368                 variableDepth(*it, next, newScope, c);
0369             
0370         }    break;
0371         case Object::apply: {
0372             const Apply *c = (const Apply*) o;
0373             
0374             Object* ul=c->ulimit(), *dl=c->dlimit(), *dn=c->domain();
0375             
0376             //uplimit and downlimit are in the parent scope
0377             if(ul) variableDepth(ul, next, scope);
0378             if(dl) variableDepth(dl, next, scope);
0379             if(dn) variableDepth(dn, next, scope);
0380             
0381             QMap<QString, int> newScope=scope;
0382             
0383             foreach(Ci* bvar, c->bvarCi()) {
0384                 newScope.insert(bvar->name(), next);
0385                 bvar->setBVarDepth(next++);
0386             }
0387             
0388             Apply::const_iterator it = c->firstValue(), itEnd=c->constEnd();
0389             for(; it!=itEnd; ++it) {
0390                 int n=next;
0391                 variableDepth(*it, n, newScope, c);
0392             }
0393         }    break;
0394         case Object::none:
0395         case Object::value:
0396         case Object::custom:
0397         case Object::oper:
0398             break;
0399     }
0400 }
0401 
0402 void Expression::computeDepth(Object* o)
0403 {
0404     if(o) {
0405         QMap<QString, int> scope;
0406         int next=0;
0407         variableDepth(o, next, scope);
0408     }
0409 }
0410 
0411 bool Expression::setMathML(const QString & s)
0412 {
0413     d->m_err.clear();
0414     delete d->m_tree;
0415     
0416     QDomDocument doc;
0417     
0418     if (!doc.setContent(s)) {
0419         d->m_err << QCoreApplication::tr("Error while parsing: %1").arg(s);
0420         return false;
0421     }
0422     
0423     d->m_tree = d->branch(doc.documentElement());
0424     
0425     computeDepth(d->m_tree);
0426     
0427     return d->m_tree;
0428 }
0429 
0430 Object* Expression::ExpressionPrivate::branch(const QDomElement& elem)
0431 {
0432     Cn *num; Operator *op;
0433     Object* ret=nullptr;
0434     
0435     if(elem.tagName()==QLatin1String("cs"))
0436         ret=listFromString(elem.text());
0437     else switch(whatType(elem.tagName())) {
0438         case Object::container: {
0439             Container::ContainerType t = Container::toContainerType(elem.tagName());
0440             
0441             if(t!=Container::none) {
0442                 Container* c=addElements<Container>(new Container(t), &elem);
0443                 
0444                 if(c && !check(c)) {
0445                     delete c;
0446                     c=nullptr;
0447                 }
0448                 ret = c;
0449             } else
0450                 m_err << QCoreApplication::translate("An error message", "Container unknown: %1").arg(elem.tagName());
0451         }    break;
0452         case Object::value:
0453             num= new Cn(0.);
0454             if(!num->setValue(elem)) {
0455                 delete num;
0456                 m_err<< QCoreApplication::tr("Cannot codify the %1 value.").arg(elem.text());
0457             } else
0458                 ret = num;
0459             break;
0460         case Object::oper:
0461             if(elem.hasChildNodes()) {
0462                 m_err << QCoreApplication::tr("The %1 operator cannot have child contexts.").arg(elem.tagName());
0463             } else {
0464                 Operator::OperatorType type=Operator::toOperatorType(elem.tagName());
0465                 if(type==Operator::none)
0466                     m_err << QCoreApplication::tr("The element '%1' is not an operator.").arg(elem.tagName());
0467                 else
0468                     ret = op = new Operator(type);
0469             }
0470             break;
0471         case Object::variable: {
0472             Ci* var = new Ci(elem.text());
0473             var->setFunction(elem.attribute(QStringLiteral("type"))==QLatin1String("function"));
0474             ret=var;
0475         }    break;
0476         case Object::vector: {
0477             ret=addElements<Vector>(new Vector(elem.childNodes().count()), &elem);
0478             if(elem.childNodes().count()==0) {
0479                 m_err << QCoreApplication::tr("Do not want empty vectors");
0480             }
0481 //             qDebug() << "PEEEEEEU" << v->size();
0482         }    break;
0483         case Object::list:
0484             ret=addElements<List>(new List, &elem);
0485             break;
0486         case Object::matrix:
0487             ret=addElements<Matrix, MatrixRow>(new Matrix, &elem);
0488             if(elem.childNodes().count()==0) {
0489                 m_err << QCoreApplication::tr("Do not want empty matrices");
0490             }
0491             break;
0492         case Object::matrixrow:
0493             ret=addElements<MatrixRow>(new MatrixRow, &elem);
0494             if(elem.childNodes().count()==0) {
0495                 m_err << QCoreApplication::tr("Do not want empty matrixrow elements");
0496             }
0497             break;
0498         case Object::apply: {
0499             Apply *a=addElements<Apply>(new Apply, &elem);
0500             if(a && !check(a)) {
0501                 delete a;
0502                 a=nullptr;
0503             }
0504             ret=a;
0505         }    break;
0506         case Object::none:
0507         case Object::custom:
0508             m_err << QCoreApplication::translate("Error message due to an unrecognized input",
0509                               "Not supported/unknown: %1").arg(elem.tagName());
0510             break;
0511     }
0512     
0513     Q_ASSERT(ret || !m_err.isEmpty());
0514     return ret;
0515 }
0516 
0517 QString Expression::toHtml() const
0518 {
0519     Q_ASSERT(isCorrect());
0520     return HtmlExpressionWriter(d->m_tree).result().toString();
0521 }
0522 
0523 QString Expression::toMathMLPresentation() const
0524 {
0525     Q_ASSERT(isCorrect());
0526     return MathMLPresentationExpressionWriter(d->m_tree).result().toString();
0527 }
0528 
0529 QString Expression::toMathML() const
0530 {
0531     Q_ASSERT(isCorrect());
0532     return MathMLExpressionWriter(d->m_tree).result().toString();
0533 }
0534 
0535 QString Expression::toString() const
0536 {
0537     Q_ASSERT(isCorrect());
0538     StringExpressionWriter s(d->m_tree);
0539     return s.result().toString();
0540 }
0541 
0542 enum Object::ObjectType Expression::whatType(const QString& tag)
0543 {
0544     Object::ObjectType ret=Object::none;
0545     if(tag==QLatin1String("cn"))
0546         ret= Object::value;
0547     else if(tag==QLatin1String("ci"))
0548         ret= Object::variable;
0549     else if(tag==QLatin1String("vector"))
0550         ret= Object::vector;
0551     else if(tag==QLatin1String("list"))
0552         ret= Object::list;
0553     else if(tag==QLatin1String("matrix"))
0554         ret= Object::matrix;
0555     else if(tag==QLatin1String("matrixrow"))
0556         ret= Object::matrixrow;
0557     else if(tag==QLatin1String("apply"))
0558         ret= Object::apply;
0559     else if(Operator::toOperatorType(tag)!=0)
0560         ret= Object::oper;
0561     else if(Container::toContainerType(tag)!=0)
0562         ret= Object::container;
0563     
0564     return ret;
0565 }
0566 
0567 bool Expression::operator==(const Expression & e) const
0568 {
0569     return AnalitzaUtils::equalTree(e.d->m_tree, d->m_tree);
0570 }
0571 
0572 bool Expression::operator!=(const Expression& e) const
0573 {
0574     return !(e==*this);
0575 }
0576 
0577 void Expression::clear()
0578 {
0579     delete d->m_tree;
0580     d->m_tree=nullptr;
0581     d->m_err.clear();
0582 }
0583 
0584 bool Expression::isCorrect() const
0585 {
0586     return !(d || d->m_tree) || d->m_err.isEmpty();
0587 }
0588 
0589 QStringList Expression::bvarList() const
0590 {
0591     Q_ASSERT(d->m_tree);
0592     const Object *o = d->m_tree;
0593     
0594     if(o->isContainer() && static_cast<const Container*>(o)->containerType()==Container::math) {
0595         if(!static_cast<const Container*>(o)->m_params.isEmpty())
0596             o = (Container*) static_cast<const Container*>(o)->m_params[0];
0597     }
0598     
0599     if(o->isApply())
0600         return static_cast<const Apply*>(o)->bvarStrings();
0601     else if(o->isContainer())
0602         return static_cast<const Container*>(o)->bvarStrings();
0603     
0604     return QStringList();
0605 }
0606 
0607 Cn Expression::toReal() const
0608 {
0609     Object* tree=d->m_tree;
0610     if(Q_LIKELY(tree && tree->type()==Object::value))
0611         return *static_cast<Cn*>(tree);
0612     else {
0613         qDebug() << "trying to return not a real value as real:" << (tree ? tree->toString() : QStringLiteral("null"));
0614         return Cn(0.);
0615     }
0616 }
0617 
0618 QString Expression::stringValue() const
0619 {
0620     Object* tree=d->m_tree;
0621     if(Q_LIKELY(d->m_tree && d->m_tree->type()==Object::list))
0622         return AnalitzaUtils::listToString(static_cast<const List*>(tree));
0623     else {
0624         qDebug() << "trying to return not a string value as string:" << (tree ? tree->toString() : QStringLiteral("null"));
0625         return QString();
0626     }
0627 }
0628 
0629 bool Expression::isString() const
0630 {
0631     return d->m_tree && d->m_tree->type()==Object::list
0632             && !static_cast<const List*>(d->m_tree)->isEmpty()
0633             && static_cast<const List*>(d->m_tree)->at(0)->type()==Object::value
0634             && static_cast<const Cn*>(static_cast<const List*>(d->m_tree)->at(0))->isCharacter();
0635 }
0636 
0637 //if it's a math element, then return the (only) son
0638 Object* actualRoot(Object* o)
0639 {
0640     if(o && o->isContainer()) {
0641         Container* c = (Container*) o;
0642         if(c->containerType()==Container::math) {
0643             return c->m_params[0];
0644         }
0645     }
0646     return o;
0647 }
0648 
0649 bool Expression::isLambda() const
0650 {
0651     Object* o = actualRoot(d->m_tree);
0652     if(o && o->isContainer()) {
0653         Container* c = (Container*) o;
0654         return c->containerType()==Container::lambda;
0655     }
0656     return false;
0657 }
0658 
0659 bool Expression::isDeclaration() const
0660 {
0661     Object* o = actualRoot(d->m_tree);
0662     if(o && o->isContainer()) {
0663         Container* c = (Container*) o;
0664         return c->containerType() == Container::declare;
0665     }
0666     return false;
0667 }
0668 
0669 QString Expression::name() const
0670 {
0671     Object* o = actualRoot(d->m_tree);
0672     if(o && o->isContainer()) {
0673         Container* c = (Container*) o;
0674         if(c->containerType() == Container::declare)
0675             return static_cast<const Ci*>(c->m_params[0])->name();
0676     }
0677     return QString();
0678 }
0679 
0680 Expression Expression::declarationValue() const
0681 {
0682     Object* o = actualRoot(d->m_tree);
0683     if(o && o->isContainer()) {
0684         Container* c = (Container*) o;
0685         if(c->containerType() == Container::declare)
0686             return Expression(c->m_params[1]->copy());
0687     }
0688     return Expression();
0689 }
0690 
0691 bool Expression::isEquation() const
0692 {
0693     Object* o = actualRoot(d->m_tree);
0694     if(o && o->isApply()) {
0695         Apply *c1 = (Apply*) o;
0696         return c1->firstOperator().operatorType()==Operator::eq;
0697     }
0698     return false;
0699 }
0700 
0701 Expression Expression::equationToFunction() const
0702 {
0703     Object* o = actualRoot(d->m_tree);
0704     if(o && o->isApply()) {
0705         Apply *c1 = (Apply*) o;
0706         if(c1->firstOperator().operatorType()==Operator::eq) {
0707             Container* c = new Container(Container::math);
0708             Apply* a = new Apply;
0709             a->appendBranch(new Operator(Operator::minus));
0710             a->appendBranch(c1->at(0)->copy());
0711             a->appendBranch(c1->at(1)->copy());
0712             c->appendBranch(a);
0713             return Expression(c);
0714         }
0715     }
0716     return *this;
0717 }
0718 
0719 QList<Ci*> Expression::parameters() const
0720 {
0721     QList<Ci*> ret;
0722     Object* o = actualRoot(d->m_tree);
0723     if(o && o->isContainer()) {
0724         Container* c1 = (Container*) o;
0725         return c1->bvarCi();
0726     }
0727     return ret;
0728 }
0729 
0730 Expression Expression::lambdaBody() const
0731 {
0732     Q_ASSERT(isLambda());
0733     Object* ob = actualRoot(d->m_tree);
0734     if(ob->isContainer()) {
0735         Container* c = (Container*) ob;
0736         Q_ASSERT(c->containerType()==Container::lambda);
0737         Object *ret = c->m_params.last();
0738         Object* o = ret->copy();
0739         computeDepth(o);
0740         return Expression(o);
0741     }
0742     return {};
0743 }
0744 
0745 bool Expression::isVector() const
0746 {
0747     Object* o = actualRoot(d->m_tree);
0748     return o && o->type()==Container::vector;
0749 }
0750 
0751 bool Expression::isMatrix() const
0752 {
0753     Object* o = actualRoot(d->m_tree);
0754     return o && o->type()==Container::matrix;
0755 }
0756 
0757 bool Expression::isList() const
0758 {
0759     Object* o = actualRoot(d->m_tree);
0760     return o && o->type()==Container::list;
0761 }
0762 
0763 QList<Expression> Expression::toExpressionList() const
0764 {
0765     bool isvector = isVector();
0766     if((!isvector && !isList()) || !d->m_tree)
0767         return QList<Expression>();
0768     
0769     QList<Expression> ret;
0770     const Object* o=actualRoot(d->m_tree);
0771 
0772     if(isvector) {
0773         const Vector* v = (const Vector*) o;
0774         for(Vector::const_iterator it=v->constBegin(), itEnd=v->constEnd(); it!=itEnd; ++it) {
0775             Object* newelement = (*it)->copy();
0776             computeDepth(newelement);
0777             ret << Expression(newelement);
0778         }
0779     } else {
0780         const List* v = (const List*) o;
0781         for(List::const_iterator it=v->constBegin(), itEnd=v->constEnd(); it!=itEnd; ++it) {
0782             Object* newelement = (*it)->copy();
0783             computeDepth(newelement);
0784             ret << Expression(newelement);
0785         }
0786     }
0787     
0788     return ret;
0789 }
0790 
0791 Expression Expression::elementAt(int position) const
0792 {
0793     Q_ASSERT(isVector());
0794     Object* o = actualRoot(d->m_tree);
0795     Q_ASSERT(o);
0796     Vector *v=static_cast<Vector*>(o);
0797     
0798     return Expression(v->at(position)->copy());
0799 }
0800 
0801 void Expression::setElementAt(int position, const Expression& exp)
0802 {
0803     Q_ASSERT(isVector());
0804     Object* o = actualRoot(d->m_tree);
0805     Q_ASSERT(o);
0806     Vector *v=static_cast<Vector*>(o);
0807     
0808     delete v->at(position);
0809     v->setAt(position, exp.tree()->copy());
0810 }
0811 
0812 QStringList Expression::error() const
0813 {
0814     return d->m_err;
0815 }
0816 
0817 void Expression::addError(const QString& error)
0818 {
0819     d->m_err += error;
0820 }
0821 
0822 const Object* Expression::tree() const
0823 {
0824     return d->m_tree;
0825 }
0826 
0827 Object* Expression::tree()
0828 {
0829     return d->m_tree;
0830 }
0831 
0832 Object* Expression::takeTree()
0833 {
0834     Object* ret = d->m_tree;
0835     setTree(Q_NULLPTR);
0836     return ret;
0837 }
0838 
0839 void Expression::setTree(Object* o)
0840 {
0841     d->m_tree=o;
0842 }
0843 
0844 bool Expression::isReal() const { return d->m_tree && d->m_tree->type()==Object::value; }
0845 bool Expression::isCustomObject() const { return d->m_tree && d->m_tree->type()==Object::custom; }
0846 
0847 Expression Expression::constructString(const QString& str)
0848 {
0849     return Expression(ExpressionPrivate::listFromString(str));
0850 }
0851 
0852 Expression Expression::constructList(const QList< Expression >& exps)
0853 {
0854     List* l = new List;
0855     foreach(const Expression& e, exps)
0856         l->appendBranch(e.tree()->copy());
0857     
0858     computeDepth(l);
0859     return Expression(l);
0860 }
0861 
0862 #define CHECK_TYPE(type)\
0863         type* a = (type *) o;\
0864         \
0865         type::iterator it=a->begin(), itEnd=a->end();\
0866         for(; it!=itEnd; ++it) {\
0867             renameTree(*it, depth, newName);\
0868         }\
0869 
0870 static void renameTree(Object* o, int depth, const QString& newName)
0871 {
0872     if(!o)
0873         return;
0874     
0875     switch(o->type()) {
0876         case Object::variable: {
0877             Ci* var = (Ci*) o;
0878             if(var->depth()==depth) 
0879                 var->setName(newName);
0880         }    break;
0881         case Object::apply: {
0882             CHECK_TYPE(Apply);
0883             renameTree(a->ulimit(), depth, newName);
0884             renameTree(a->dlimit(), depth, newName);
0885             renameTree(a->domain(), depth, newName);
0886         }    break;
0887         case Object::container: { CHECK_TYPE(Container); } break;
0888         case Object::list: { CHECK_TYPE(List); } break;
0889         case Object::vector: { CHECK_TYPE(Vector); } break;
0890         case Object::matrix: { CHECK_TYPE(Matrix); } break;
0891         case Object::matrixrow: { CHECK_TYPE(MatrixRow); } break;
0892         
0893         case Object::none:
0894         case Object::value:
0895         case Object::oper:
0896         case Object::custom:
0897             break;
0898     }
0899 }
0900 
0901 void Expression::renameArgument(int depth, const QString& newName)
0902 {
0903     renameTree(d->m_tree, depth, newName);
0904     computeDepth(d->m_tree);
0905 }
0906 
0907 Expression Expression::constructCustomObject(const QVariant& custom, CustomObjectDestructor d)
0908 {
0909     Object* obj = new CustomObject(custom, d);
0910     return Expression(obj);
0911 }
0912 
0913 QVariant Expression::customObjectValue() const
0914 {
0915     Object* tree=d->m_tree;
0916     if(Q_LIKELY(tree && tree->type()==Object::custom))
0917         return static_cast<const CustomObject*>(tree)->value();
0918     else {
0919         qDebug() << "trying to return as a custom object something that it is not:" << (tree ? tree->toString() : QStringLiteral("null"));
0920         return QVariant();
0921     }
0922 }
0923 
0924 // static void print_dom(const QDomNode& in, int ind)
0925 // {
0926 //     QString a;
0927 //
0928 //     if(ind >100){
0929 //         qDebug("...");
0930 //         return;
0931 //     }
0932 //
0933 //     for(int i=0; i<ind; i++)
0934 //         a.append("______|");
0935 //
0936 //     if(in.hasChildNodes())
0937 //         qDebug("%s%s(%s) -- %d", qPrintable(a), qPrintable(in.toElement().tagName()), qPrintable(in.toElement().text()), in.childNodes().length());
0938 //     else
0939 //         qDebug("%s%s", qPrintable(a), qPrintable(in.toElement().tagName()));
0940 //
0941 //     for(int i=0 ; i<in.childNodes().length(); i++){
0942 //         if(in.childNodes().item(i).isElement())
0943 //             print_dom(in.childNodes().item(i), ind+1);
0944 //     }
0945 // }
0946 
0947 bool Expression::isCompleteExpression(const QString& exp, bool justempty)
0948 {
0949     ExpLexer lex(exp);
0950     return lex.isCompleteExpression(justempty);
0951 }
0952 
0953 QStringList Expression::comments() const
0954 {
0955     return m_comments;
0956 }
0957 
0958 #include "moc_expression.cpp"