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

0001 /*************************************************************************************
0002  *  Copyright (C) 2007-2010 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 
0019 #include "apply.h"
0020 #include "abstractexpressionvisitor.h"
0021 #include <QStringList>
0022 #include "variable.h"
0023 #include "analitzautils.h"
0024 #include "container.h"
0025 
0026 using namespace Analitza;
0027 
0028 Apply::Apply()
0029     : Object(apply), m_ulimit(nullptr), m_dlimit(nullptr), m_domain(nullptr), m_op(Operator::function)
0030 {}
0031 
0032 Apply::~Apply()
0033 {
0034     delete m_dlimit;
0035     delete m_ulimit;
0036     delete m_domain;
0037     qDeleteAll(m_bvars);
0038     qDeleteAll(m_params);
0039 }
0040 
0041 bool Apply::addBranch(Object* o)
0042 {
0043     if(o->type()==Object::oper) {
0044         m_op = *static_cast<Operator*>(o);
0045         delete o;
0046     } else if(o->isContainer()) {
0047         Container* c=static_cast<Container*>(o);
0048         switch(c->containerType()) {
0049             case Container::uplimit:
0050                 Q_ASSERT(!m_ulimit);
0051                 m_ulimit = c->m_params[0];
0052                 c->m_params[0]=nullptr;
0053                 delete c;
0054                 break;
0055             case Container::downlimit:
0056                 Q_ASSERT(!m_dlimit);
0057                 m_dlimit = c->m_params[0];
0058                 c->m_params[0]=nullptr;
0059                 delete c;
0060                 break;
0061             case Container::domainofapplication:
0062                 Q_ASSERT(!m_domain);
0063                 m_domain = c->m_params[0];
0064                 c->m_params[0]=nullptr;
0065                 delete c;
0066                 break;
0067             case Container::bvar:
0068                 Q_ASSERT(c->m_params[0]->type()==variable);
0069                 m_bvars += static_cast<Ci*>(c->m_params[0]);
0070                 c->m_params[0]=nullptr;
0071                 delete c;
0072                 break;
0073             default:
0074                 return false;
0075         }
0076     } else
0077         return false;
0078     
0079     return true;
0080 }
0081 
0082 void Apply::appendBranch(Object *o)
0083 {
0084     if(!addBranch(o))
0085         m_params.append(o);
0086 }
0087 
0088 void Apply::prependBranch(Object* o)
0089 {
0090     if(!addBranch(o))
0091         m_params.prepend(o);
0092 }
0093 
0094 QVariant Apply::accept(AbstractExpressionVisitor* exp) const
0095 {
0096     return exp->visit(this);
0097 }
0098 
0099 QStringList Apply::bvarStrings() const
0100 {
0101     QStringList ret;
0102     foreach(const Ci* bvar, m_bvars) {
0103         ret.append(bvar->name());
0104     }
0105     return ret;
0106 }
0107 
0108 bool Apply::operator==(const Apply& a) const
0109 {
0110     bool eq=a.m_params.count()==m_params.count() && a.firstOperator()==firstOperator();
0111     eq &= bool(a.ulimit())==bool(m_ulimit);
0112     eq &= bool(a.dlimit())==bool(m_dlimit);
0113     eq &= bool(a.domain())==bool(m_domain);
0114     
0115     if(m_ulimit) eq &= AnalitzaUtils::equalTree(m_ulimit, a.m_ulimit);
0116     if(m_dlimit) eq &= AnalitzaUtils::equalTree(m_dlimit, a.m_dlimit);
0117     if(m_domain) eq &= AnalitzaUtils::equalTree(m_domain, a.m_domain);
0118     
0119     for(int i=0; eq && i<m_params.count(); ++i) {
0120         Object *o=m_params[i], *o1=a.m_params[i];
0121         eq = eq && AnalitzaUtils::equalTree(o, o1);
0122     }
0123     
0124     return eq;
0125 }
0126 
0127 Apply* Apply::copy() const
0128 {
0129     Apply* ret=new Apply;
0130     ret->m_dlimit = m_dlimit? m_dlimit->copy() : nullptr;
0131     ret->m_ulimit = m_ulimit? m_ulimit->copy() : nullptr;
0132     ret->m_domain = m_domain? m_domain->copy() : nullptr;
0133     ret->m_op     = m_op;
0134     
0135     foreach(const Ci* var, m_bvars)
0136         ret->m_bvars += (Ci*) var->copy();
0137     
0138     foreach(const Object* o, m_params)
0139         ret->m_params += o->copy();
0140     
0141     return ret;
0142 }
0143 
0144 bool Apply::matches(const Object* exp, QMap<QString, const Object*>* found) const
0145 {
0146     if(Object::apply!=exp->type())
0147         return false;
0148     const Apply* c=(const Apply*) exp;
0149     if(m_params.count()!=c->m_params.count())
0150         return false;
0151     
0152     QVector<Ci*> vars=m_bvars, cvars = c->bvarCi();
0153     bool matching=vars.size()==cvars.size();
0154     matching &= m_op.matches(&c->m_op, found);
0155     
0156     for(QVector<Ci*>::const_iterator it=vars.constBegin(), cit=cvars.constBegin(), itEnd=vars.constEnd(); matching && it!=itEnd; ++it) {
0157         matching &= (*it)->matches(*cit, found);
0158     }
0159     
0160 //     bool matching=true;
0161     Apply::const_iterator it, it2, itEnd=m_params.constEnd();
0162     for(it=m_params.constBegin(), it2=c->m_params.constBegin(); matching && it!=itEnd; ++it, ++it2)
0163         matching &= (*it)->matches(*it2, found);
0164     
0165     matching &= bool(m_ulimit)==bool(c->m_ulimit) && (!m_ulimit || m_ulimit->matches(c->m_ulimit, found));
0166     matching &= bool(m_dlimit)==bool(c->m_dlimit) && (!m_dlimit || m_dlimit->matches(c->m_dlimit, found));
0167     matching &= bool(m_domain)==bool(c->m_domain) && (!m_domain || m_domain->matches(c->m_domain, found));
0168     return matching;
0169 }
0170 
0171 bool Analitza::Apply::hasBoundings() const
0172 {
0173     return m_dlimit || m_ulimit || m_domain;
0174 }
0175 
0176 void Apply::addBVar(Ci* bvar)
0177 {
0178     m_bvars += bvar;
0179 }
0180 
0181 Object* Apply::at(int p) const
0182 {
0183     return m_params.at(p);
0184 }