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

0001 /*************************************************************************************
0002  *  Copyright (C) 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 "expressiontypechecker.h"
0020 #include "variable.h"
0021 #include "variables.h"
0022 #include "list.h"
0023 #include "vector.h"
0024 #include "container.h"
0025 #include "expression.h"
0026 #include "analitzautils.h"
0027 #include "operations.h"
0028 #include "apply.h"
0029 #include "value.h"
0030 #include "matrix.h"
0031 #include <QCoreApplication>
0032 
0033 QDebug operator<<(QDebug dbg, const Analitza::ExpressionType &c)
0034 {
0035     dbg.nospace() << "("<< qPrintable(c.toString());
0036 //     if(!c.assumptions().isEmpty())
0037 //         dbg.nospace() <<", " << c.assumptions();
0038     dbg.nospace() << /*":"<< c.type() <<*/")";
0039     
0040     return dbg.space();
0041 }
0042 
0043 QDebug operator<<(QDebug dbg, const QMap<int, Analitza::ExpressionType> &c)
0044 {
0045     dbg.nospace() << "starsMap(";
0046     for(QMap<int,Analitza::ExpressionType>::const_iterator it=c.constBegin(); it!=c.constEnd(); ++it) {
0047         QString str = Analitza::ExpressionType(Analitza::ExpressionType::Any, it.key()<0? -it.key():it.key()).toString();
0048         if(it.key()<0)
0049             str="<-"+str+"->";
0050         
0051         dbg.space() << "["<< str << ":" << it.value() << "]";
0052     }
0053     dbg.space() << ")";
0054     
0055     return dbg.nospace();
0056 }
0057 
0058 namespace Analitza
0059 {
0060 
0061 void printAssumptions(const QString& prefix, const ExpressionType& current)
0062 {
0063     qDebug() << qPrintable(prefix) << current << current.assumptions();
0064     if(current.type()==ExpressionType::Many) {
0065         foreach(const ExpressionType& t, current.alternatives()) {
0066             qDebug() << qPrintable(prefix) << "XXXSSS" << t << t.assumptions();
0067         }
0068     }
0069     qDebug() << qPrintable(prefix) << "--";
0070 }
0071 
0072 ExpressionTypeChecker::ExpressionTypeChecker(Variables* v)
0073     : m_stars(0)
0074     , m_v(v)
0075 {}
0076 
0077 ExpressionType ExpressionTypeChecker::check(const Expression& exp)
0078 {
0079     m_deps.clear();
0080     m_stars=1;
0081     current=ExpressionType(ExpressionType::Error);
0082     
0083     exp.tree()->accept(this);
0084     
0085 //     qDebug() << "cheeeeeeck" << m_vars;
0086     return current;
0087 }
0088 
0089 QVariant ExpressionTypeChecker::visit(const Operator*) { Q_ASSERT(false && "should not get here"); return QVariant(); }
0090 
0091 bool ExpressionTypeChecker::inferType(const ExpressionType& found, const ExpressionType& targetType, QMap<QString, ExpressionType>* assumptions)
0092 {
0093     Q_ASSERT(!targetType.isError() && assumptions);
0094     Q_ASSERT(found.type()!=ExpressionType::Many);
0095     
0096     QMap<int, ExpressionType> stars;
0097     stars=ExpressionType::computeStars(stars, found, targetType);
0098     bool ret=found.canReduceTo(targetType);
0099     ret&=ExpressionType::matchAssumptions(&stars, found.assumptions(), targetType.assumptions());
0100     ret&=ExpressionType::assumptionsMerge(*assumptions, found.assumptions());
0101     
0102     for(QMap<QString, ExpressionType>::iterator it=assumptions->begin(), itEnd=assumptions->end(); it!=itEnd; ++it) {
0103         *it=it->starsToType(stars);
0104     }
0105 //     qDebug() << "fuuuuu" << stars << *assumptions << ret;
0106     
0107     return ret;
0108 }
0109 
0110 QList<ExpressionType> ExpressionTypeChecker::computePairs(const QList<ExpressionType>& options, const ExpressionType& param)
0111 {
0112     QList<ExpressionType> ret;
0113     
0114     if(param.type()==ExpressionType::Any) {
0115         int basestars=m_stars;
0116         foreach(const ExpressionType& opt, options) {
0117             ExpressionType toadd=opt;
0118             m_stars=qMax<int>(m_stars, toadd.increaseStars(basestars));
0119             QMap<int, ExpressionType> stars;
0120             
0121             //We know the parameter is any, we don't have to infer
0122             stars=ExpressionType::computeStars(stars, param, toadd.parameters().first());
0123             
0124             toadd.parameters().last().addAssumptions(param.assumptions());
0125             toadd.parameters().last()=toadd.parameters().last().starsToType(stars);
0126             ret += toadd;
0127         }
0128     } else 
0129         foreach(const ExpressionType& opt, options) {
0130             if(opt.parameters().at(0).canReduceTo(param)) {//Infer on param!=param but canReduce?
0131                 QMap<int, ExpressionType> stars = ExpressionType::computeStars(QMap<int, ExpressionType>(), opt.parameters().at(0), param);
0132                 ret += opt.starsToType(stars);
0133             }
0134         }
0135     
0136 //     qDebug() << "_______" << param << exp->toString() << ret;
0137     return ret;
0138 }
0139 
0140 ExpressionType ExpressionTypeChecker::solve(const Operator* o, const QVector< Object* >& parameters)
0141 {
0142     Q_ASSERT(o->operatorType()!=Operator::function);
0143     
0144     QList<ExpressionType> paramtypes;
0145     for(QVector<Object*>::const_iterator it=parameters.constBegin(), itEnd=parameters.constEnd(); it!=itEnd; ++it) {
0146         (*it)->accept(this);
0147         paramtypes += current;
0148     }
0149     
0150     QList<ExpressionType> ret;
0151     if(parameters.size()==1) {
0152         QList<ExpressionType> types=paramtypes.first().type()==ExpressionType::Many ? paramtypes.first().alternatives() : QList<ExpressionType>() << paramtypes.first();
0153 //         const QMap<QString, ExpressionType> assumptions=current.assumptions();
0154         
0155         foreach(const ExpressionType& t, types) {
0156             QList<ExpressionType> thing=computePairs(Operations::inferUnary(o->operatorType()), t);
0157             foreach(const ExpressionType& opt, thing) {
0158                 ExpressionType tt(opt.parameters().constLast());
0159                 tt.addAssumptions(t.assumptions());
0160                 ret+=tt;
0161             }
0162         }
0163 //         qDebug() << "bam" << ret ;
0164     } else {
0165         Q_ASSERT(parameters.size()>=2);
0166 //         QMap<int, ExpressionType> stars;
0167         
0168         ExpressionType firstType=paramtypes.first();
0169         QList<ExpressionType> firstTypes= firstType.type()==ExpressionType::Many ?  firstType.alternatives() : QList<ExpressionType>() << firstType;
0170         
0171         const QList<ExpressionType> res=Operations::infer(o->operatorType());
0172         
0173         bool firstPair=true;
0174         for(QList<ExpressionType>::const_iterator it=paramtypes.constBegin()+1, itEnd=paramtypes.constEnd(); it!=itEnd; ++it, firstPair=false)
0175         {
0176             ExpressionType secondType=*it;
0177             
0178             QList<ExpressionType> secondTypes=secondType.type()==ExpressionType::Many ? secondType.alternatives() : QList<ExpressionType>() << secondType;
0179             int starsbase=m_stars;
0180 //             static int ind=3;
0181 //             qDebug() << qPrintable("+" +QString(ind++, '-')) << o->toString() << firstType << secondType;
0182             
0183             bool found = false;
0184             foreach(const ExpressionType& _first, firstTypes) {
0185                 foreach(const ExpressionType& _second, secondTypes) {
0186                     QMap<int, ExpressionType> _starToType;
0187                     bool matches=ExpressionType::matchAssumptions(&_starToType, _first.assumptions(), _second.assumptions());
0188                     
0189                     if(!matches) {
0190 //                         qDebug() << "peee" << ExpressionType::wrongAssumptions(_first.assumptions(), _second.assumptions());
0191                         continue;
0192                     }
0193                     foreach(const ExpressionType& _opt, res) {
0194                         ExpressionType opt(_opt);
0195                         m_stars=qMax<int>(m_stars, opt.increaseStars(starsbase));
0196                         
0197                         Q_ASSERT(!opt.parameters().last().isError());
0198                         QMap<int, ExpressionType> starToType, starToParam;
0199                         
0200                         bool valid = false;
0201                         QMap<QString, ExpressionType> assumptions;
0202                         
0203                         //NOTE In matrix multiplication (A*B) A may or not be reduced to B, since is allowed 
0204                         //different matrix sizes provided that are valid sizes for the multiplication, 
0205                         //thus we need a special case for matrix type
0206                         if (current.type() == ExpressionType::Matrix) {
0207                             ExpressionType first =_first .starsToType(_starToType);
0208                             ExpressionType second=_second.starsToType(_starToType);
0209                             
0210     //                         qDebug() << "9999999" << _first.assumptions() << first.assumptions() << starToType;
0211                             
0212                             starToType=ExpressionType::computeStars(starToType, first,  opt.parameters()[0]);
0213                             first =first .starsToType(starToType);
0214                             starToType=ExpressionType::computeStars(starToType, second, opt.parameters()[1]);
0215                             second=second.starsToType(starToType);
0216                             
0217                             assumptions=first.assumptions();
0218                             valid=ExpressionType::assumptionsMerge(assumptions, second.assumptions());
0219                             
0220     //                         qDebug() << "PPPPPP" << opt << first << second << "|||||" << first.assumptions() << second.assumptions();
0221                             
0222                             valid &= !first.isError() && !second.isError();
0223                             starToParam=ExpressionType::computeStars(starToParam, opt.parameters()[0], first);
0224     //                         qDebug() << "XXXXXX1" << starToParam;
0225                             valid &= first .canReduceTo(opt.parameters()[0].starsToType(starToParam));
0226                             starToParam=ExpressionType::computeStars(starToParam, opt.parameters()[1], second);
0227     //                         qDebug() << "XXXXXX2" << starToParam;
0228                             valid &= second.canReduceTo(opt.parameters()[1].starsToType(starToParam));
0229                         } else {
0230                             ExpressionType first =_first .starsToType(_starToType);
0231                             ExpressionType second=_second.starsToType(_starToType);
0232     //                         qDebug() << "9999999" << _first.assumptions() << first.assumptions() << starToType;
0233                             
0234                             starToType=ExpressionType::computeStars(starToType, first,  opt.parameters()[0]);
0235                             starToType=ExpressionType::computeStars(starToType, second, opt.parameters()[1]);
0236                             
0237                             first =first .starsToType(starToType);
0238                             second=second.starsToType(starToType);
0239                             
0240                             starToParam=ExpressionType::computeStars(starToParam, opt.parameters()[0], first);
0241                             starToParam=ExpressionType::computeStars(starToParam, opt.parameters()[1], second);
0242     //                         qDebug() << "XXXXXX" << starToParam;
0243     //                         qDebug() << "PPPPPP" << opt << first << second << "|||||" << first.assumptions() << second.assumptions();
0244                             
0245     //                         starToType=ExpressionType::computeStars(starToType, first,  opt.parameters()[0].starsToType(starToParam));
0246     //                         starToType=ExpressionType::computeStars(starToType, second, opt.parameters()[1].starsToType(starToParam));
0247                             
0248     //                         first =first .starsToType(starToType);
0249     //                         second=second.starsToType(starToType);
0250                             
0251                             assumptions=first.assumptions();
0252                             valid=ExpressionType::assumptionsMerge(assumptions, second.assumptions());
0253                             
0254     //                         qDebug() << "fifuuuuuuu" << first << (it-1)->toString() << 
0255     //                                                     second << it->toString() << assumptions << valid;
0256                             
0257                             valid &= !first.isError() && !second.isError();
0258                             valid &= first .canReduceTo(opt.parameters()[0].starsToType(starToParam));
0259                             valid &= second.canReduceTo(opt.parameters()[1].starsToType(starToParam));
0260                             
0261     //                         qDebug() << "POPOPO" << (it-1)->toString() << it->toString() << valid << first << second << starToParam;
0262                         }
0263                         
0264 //                         qDebug() << "POPOPO" << (it-1)->toString() << it->toString() << valid << first << second << starToParam;
0265                         if(valid) {
0266                             ExpressionType toadd=opt.parameters().last();
0267                             toadd.addAssumptions(assumptions);
0268                             toadd=toadd.starsToType(starToParam);
0269                             
0270                             if(firstPair) {
0271                                 ret += toadd;
0272                                 found = true;
0273                             } else {
0274                                 QList<ExpressionType>::iterator it=ret.begin(), itEnd=ret.end();
0275                                 for(; it!=itEnd; ++it) {
0276                                     QMap<int, ExpressionType> stars;
0277                                     if(toadd.canReduceTo(*it) && ExpressionType::matchAssumptions(&stars, it->assumptions(), toadd.assumptions())) {
0278                                         bool b=ExpressionType::assumptionsMerge(it->assumptions(), toadd.starsToType(stars).assumptions());
0279                                         Q_ASSERT(b);
0280                                         found = true;
0281                                         break;
0282                                     } else if(it->canReduceTo(toadd) && ExpressionType::matchAssumptions(&stars, it->assumptions(), toadd.assumptions())) {
0283                                         toadd=toadd.starsToType(stars);
0284                                         bool b=ExpressionType::assumptionsMerge(toadd.assumptions(), it->assumptions());
0285                                         Q_ASSERT(b);
0286                                         *it=toadd;
0287                                         found = true;
0288                                         break;
0289                                     }
0290                                 }
0291                             }
0292                         }
0293 //                         else
0294 //                         {
0295 //                             qDebug() << "lalala" << first << second;
0296 //                         }
0297                     }
0298                 }
0299             }
0300             if(!found) {
0301                 addError(QCoreApplication::tr("Could not find a type that unifies '%1'").arg(o->toString()));
0302             }
0303 //             qDebug() << qPrintable("\\"+QString(--ind, '-')) << o->toString() << ret;
0304         }
0305     }
0306     
0307     if(ret.isEmpty())
0308         return ExpressionType(ExpressionType::Error);
0309     else if(ret.count()==1)
0310         return ret.first();
0311     else {
0312         ExpressionType t(ExpressionType::Many);
0313         foreach(const ExpressionType& alt, ret)
0314             t.addAlternative(alt);
0315         return t;
0316     }
0317 }
0318 
0319 QVariant ExpressionTypeChecker::visit(const Ci* var)
0320 {
0321     if(m_typeForBVar.contains(var->name())) {
0322         current=m_typeForBVar.value(var->name());
0323     } else if(!m_lambdascope.contains(var->name()) && isVariableDefined(var->name())) {
0324         current=typeForVar(var->name());
0325     } else {
0326         current=ExpressionType(Analitza::ExpressionType::Any, m_stars++);
0327         bool ret = current.addAssumption(var->name(), current);
0328         Q_ASSERT(ret);
0329         
0330         if(var->depth()<0 && !isVariableDefined(var->name()) && !m_calculating.contains(var->name()))
0331             m_deps += var->name();
0332     }
0333     
0334     return QString();
0335 }
0336 
0337 bool ExpressionTypeChecker::isVariableDefined(const QString& id) const
0338 {
0339     return m_v->contains(id) || m_vars.contains(id);
0340 }
0341 
0342 QVariant ExpressionTypeChecker::visit(const Cn* c)
0343 {
0344     ExpressionType::Type type;
0345     
0346     switch(c->format()) {
0347         case Cn::Boolean:
0348             type=ExpressionType::Bool;
0349             break;
0350         case Cn::Char:
0351             type=ExpressionType::Char;
0352             break;
0353         default:
0354             type=ExpressionType::Value;
0355             break;
0356     }
0357     
0358     current=ExpressionType(type);
0359     return QString();
0360 }
0361 
0362 QStringList objectsToString(const QList<Object*>& objs) {
0363     QStringList ret;
0364     foreach(const Object* o, objs) {
0365         ret+=o->toString();
0366     }
0367     return ret;
0368 }
0369 
0370 ExpressionType ExpressionTypeChecker::commonType(const QList<Object*>& values)
0371 {
0372     ExpressionType ret;
0373     
0374     if(values.isEmpty()) {
0375         ret=ExpressionType(ExpressionType::Any, m_stars++);
0376     } else foreach(const Object* o, values) {
0377         o->accept(this);
0378         
0379 //         qDebug()<< "sususu" << current << ret << "||" << current.assumptions() << ret.assumptions();
0380         
0381 //         qDebug() << "falala" << ret << current << stars;
0382         QList<ExpressionType> retalts;
0383         QList<ExpressionType> alts1=current.type()==ExpressionType::Many ? current.alternatives() : QList<ExpressionType>() << current;
0384         QList<ExpressionType> alts2=ret.type()==ExpressionType::Many ? ret.alternatives() : QList<ExpressionType>() << ret;
0385 // #error foreach + canReduce + computestars to tell that type of:foldr1==f==elems
0386         
0387         foreach(const ExpressionType& t1, alts1) {
0388             QMap<int, ExpressionType> _stars;
0389             QMap<QString, ExpressionType> assumptions(ret.assumptions());
0390             bool b=ExpressionType::matchAssumptions(&_stars, current.assumptions(), assumptions);
0391             b &= ExpressionType::assumptionsMerge(assumptions, current.assumptions());
0392             if(!b) {
0393                 continue;
0394             }
0395             
0396             foreach(const ExpressionType& t2, alts2) {
0397                 QMap<int, ExpressionType> stars(_stars);
0398                 
0399 //                 printAssumptions("commonnnnXX", t1);
0400 //                 printAssumptions("commonnnnYY", t2);
0401                 ExpressionType rr=ExpressionType::minimumType(t1, t2);
0402                 if(!rr.isError() && ExpressionType::matchAssumptions(&stars, t2.assumptions(), t1.assumptions())) {
0403                     stars=ExpressionType::computeStars(stars, t2, t1);
0404                     bool b=ExpressionType::assumptionsMerge(rr.assumptions(), assumptions);
0405 //                     Q_ASSERT(b);
0406 //                     qDebug() << "*************" << o->toString() << rr << b << "||||||" << stars;
0407 //                     printAssumptions("commonnnnWW", rr);
0408                     if(b)
0409                         retalts += rr.starsToType(stars);
0410 //                     printAssumptions("commonnnnZZ", retalts.last());
0411                 }
0412             }
0413         }
0414         
0415         if(retalts.size()==1)
0416             ret=retalts.first();
0417         else if(retalts.isEmpty())
0418             ret=ExpressionType::Error;
0419         else
0420             ret=ExpressionType(ExpressionType::Many, retalts);
0421     }
0422     
0423 //     printAssumptions("ffffffff", ret);
0424     
0425     return ret;
0426 }
0427 
0428 QVariant ExpressionTypeChecker::visit(const Apply* c)
0429 {
0430     QMap<QString, ExpressionType> ctx=m_typeForBVar;
0431     QMap<QString, ExpressionType> assumptions;
0432     Operator o=c->firstOperator();
0433     
0434     if(o.isBounded()) {
0435         Object* ul=c->ulimit();
0436         ExpressionType tt;
0437         if(ul) {
0438             Object* dl=c->dlimit();
0439             ul->accept(this);
0440             
0441             tt=current; //FIXME: should remove when done
0442             if(!current.isError() && current.type()!=ExpressionType::Any)
0443                 assumptions=typeIs(dl, ExpressionType(current));
0444             else {
0445                 dl->accept(this);
0446                 tt=current;
0447                 
0448                 if(!current.isError())
0449                     assumptions=typeIs(ul, ExpressionType(current));
0450             }
0451         } else if(c->domain()) {
0452             c->domain()->accept(this);
0453             
0454             if(current.type()==ExpressionType::Any) {
0455                 ExpressionType anyItem(ExpressionType::Any, m_stars++);
0456                 
0457                 ExpressionType anyList(ExpressionType::List, anyItem);
0458                 ExpressionType anyVector(ExpressionType::Vector, anyItem, -1);
0459                 ExpressionType anyMatrix(ExpressionType::Matrix, ExpressionType(ExpressionType::Vector, anyItem, -2), -3);
0460                 
0461                 ExpressionType anyContainer(ExpressionType::Many);
0462                 anyContainer.addAlternative(anyList);
0463                 anyContainer.addAlternative(anyVector);
0464                 anyContainer.addAlternative(anyMatrix);
0465                 
0466                 bool ret = anyItem.addAssumption(static_cast<Ci*>(c->domain())->name(), anyContainer);
0467                 if(ret)
0468                     tt=anyItem;
0469             } else if(current.type()==ExpressionType::Vector || current.type()==ExpressionType::List || current.type()==ExpressionType::Matrix) {
0470                 tt=current.contained();
0471                 tt.addAssumptions(current.assumptions());
0472             } else
0473                 addError(QCoreApplication::tr("The domain should be either a vector or a list"));
0474             //TODO: should control the many case
0475         }
0476         
0477         //FIXME: should remove when done
0478         foreach(const QString& s, c->bvarStrings())
0479             m_typeForBVar[s]=ExpressionType(tt);
0480     }
0481     
0482     switch(o.operatorType()) {
0483         case Operator::none:
0484         case Operator::sum:
0485         case Operator::product:
0486             (*c->firstValue())->accept(this);
0487             current.addAssumptions(assumptions);
0488             break;
0489         case Operator::diff:
0490             //TODO Check inside
0491             
0492             current=ExpressionType(ExpressionType::Lambda);
0493             current.addParameter(ExpressionType::Value);
0494             current.addParameter(ExpressionType::Value);
0495             break;
0496         case Operator::function: {
0497 //                     qDebug() << "calling" << c->toString();
0498             c->m_params.first()->accept(this);
0499 //                     qDebug() << "retrieved lambda" << c->m_params.first()->toString() << current << current.assumptions();
0500             ExpressionType returned = current;
0501             assumptions=current.assumptions();
0502             
0503             QList<ExpressionType> exps;
0504             Apply::const_iterator it=c->firstValue()+1, itEnd=c->constEnd();
0505             for(; it!=itEnd; ++it) {
0506                 (*it)->accept(this);
0507                 
0508                 exps += current;
0509             }
0510             
0511             if(returned.type()==ExpressionType::Any) {
0512                 ExpressionType ret=ExpressionType(ExpressionType::Any, m_stars++);
0513 //                 qDebug() << "fffffffffffffff" << m_stars;
0514                 ret.addAssumptions(assumptions);
0515                 
0516                 exps += ret;
0517                 QList<ExpressionType> t=ExpressionType::lambdaFromArgs(exps);
0518 //                 qDebug() << "OOOOOOOOOOOOOOOOOOOOOOO" << c->toString() << ret /*<< stars*/ << ret.assumptions() << "||||" << t << exps;
0519                 
0520                 ExpressionType ret2(ExpressionType::Many);
0521                 bool error=false;
0522                 foreach(const ExpressionType& type, t) {
0523                     ExpressionType returntype(type.parameters().constLast());
0524                     returntype.addAssumptions(type.assumptions());
0525                     if(c->m_params.first()->type()==Object::variable) {
0526                         QString name=static_cast<Ci*>(c->m_params.first())->name();
0527                         QMap<QString, ExpressionType>::const_iterator itf=returntype.assumptions().constFind(name);
0528                         
0529                         if(itf!=returntype.assumptions().constEnd() && itf->type()==ExpressionType::Lambda) {
0530                             ExpressionType oldt=ExpressionType::minimumType(*itf, type);
0531                             error=!oldt.addAssumption(name, oldt);
0532                             if(error)
0533                                 break;
0534                             QMap<int,ExpressionType> stars;
0535                             stars=ExpressionType::computeStars(stars, type, oldt);
0536                             bool b=ExpressionType::matchAssumptions(&stars, oldt.assumptions(), type.assumptions());
0537                             Q_ASSERT(b);
0538                             
0539                             oldt=oldt.starsToType(stars);
0540 //                             qDebug() << "hmmm..." << oldt << stars << type << "::::::\n\t" << oldt.assumptions() << "\n\t" << type.assumptions();
0541                             returntype=oldt.parameters().constLast();
0542 //                             printAssumptions("reeeeet", returntype);
0543                             
0544                             error = !returntype.addAssumption(name, oldt); //can't happen, we already checked it's not an assumption
0545                             Q_ASSERT(!error);
0546                         } else {
0547                             error = !returntype.addAssumption(name, type);
0548                             if(error)
0549                                 break;
0550                         }
0551                     }
0552                     returntype.addAssumptions(type.assumptions());
0553                     
0554                     ret2.addAlternative(returntype);
0555                 }
0556                 
0557                 if(error) {
0558                     addError(QCoreApplication::translate("type error message", "Cannot call '%1'").arg(c->m_params.first()->toString()));
0559                     current=ExpressionType(ExpressionType::Error);
0560                 } else
0561                     current=ret2;
0562             } else if(returned.isError()) {
0563                 current=ExpressionType(ExpressionType::Error);
0564             }
0565             else {
0566                 ExpressionType ret(ExpressionType::Many), signature(returned);
0567                 
0568                 QList<ExpressionType> alts=signature.type()==ExpressionType::Many ? signature.alternatives() : QList<ExpressionType>() << signature;
0569                 QList<ExpressionType> args=ExpressionType::lambdaFromArgs(exps);
0570                 bool exit=false;
0571                 foreach(const ExpressionType& opt, alts) {
0572                     if(opt.type()!=ExpressionType::Lambda) {
0573 //                                 addError(i18n("We can only call functions."));
0574                         continue;
0575                     }
0576                     
0577                     const bool isvariadic = (opt.parameters().at(0).type() == ExpressionType::Any);
0578                     //if we have a variadic check only the return type (that is why we put 0 as args count here)
0579                     const int nargs = opt.parameters().size()-1;
0580                     
0581                     foreach(const ExpressionType& f, args) {
0582                         QList<ExpressionType> altargs=f.parameters();
0583                         
0584                         bool valid=true;
0585                         
0586                         if (isvariadic) { // if is variadic don't check the number of args
0587                             Q_ASSERT(opt.parameters().size() == 2); // Any and return type
0588                             
0589                             //when use Any with contained we need to check if all args must be of the contained type
0590                             if (opt.parameters().at(0).hasContained()) {
0591                                 for(int i=0; valid && i<altargs.size(); i++) {
0592                                     if(!altargs[i].canReduceTo(opt.parameters().at(0).contained())) {
0593                                         addError(QCoreApplication::tr("Cannot reduce '%1' to '%2'. Invalid type of parameter '%3' for '%4'").
0594                                         arg(altargs[i].toString(), opt.parameters().at(0).contained().toString()).
0595                                         arg(i+1).
0596                                         arg(c->toString()));
0597                                         
0598                                         valid=false;
0599                                         break;
0600                                     }
0601                                 }
0602                             }
0603                         } else if(opt.parameters().size()!=altargs.size()+1) {
0604                             addError(QCoreApplication::tr("Invalid parameter count for '%2'. Should have %1 parameters.").arg(opt.parameters().size()-1).arg(c->toString()));
0605                             exit=true;
0606                             break;
0607                         }
0608                         
0609                         QMap<QString, ExpressionType> assumptions;
0610                         QMap<int, ExpressionType> starToType, starToParam;
0611                         
0612                         for(int i=0; valid && i<nargs; i++) {
0613                             if (i<opt.parameters().size() && i<altargs.size()) {
0614                                 if(!altargs[i].canCompareTo(opt.parameters().at(i))) {
0615                                     if (isvariadic)
0616                                         addError(QCoreApplication::tr("Cannot compare '%1' to '%2'. Invalid type of parameter '%3' for '%4'").
0617                                         arg(altargs[i].toString(), opt.parameters().at(i).toString()).
0618                                         arg(i+1).
0619                                         arg(c->toString()));
0620                                     
0621                                     valid=false;
0622                                     break;
0623                                 }
0624                                 
0625                                 starToType=ExpressionType::computeStars(starToType, opt.parameters().at(i), altargs[i]);
0626                                 
0627                                 ExpressionType t=opt.parameters().at(i).starsToType(starToType);
0628                                 starToParam=ExpressionType::computeStars(starToParam, altargs[i], t);
0629                                 valid=!t.isError() && inferType(altargs[i].starsToType(starToParam), t, &assumptions);
0630                                 
0631 //                                 qDebug() << "pepeluis" << c->toString() << c->m_params[i+1]->toString() << altargs[i] << t << valid;
0632                             }
0633                         }
0634                         
0635                         valid &= ExpressionType::matchAssumptions(&starToType, opt.parameters().constLast().assumptions(), assumptions);
0636                         
0637                         if(valid) {
0638                             ExpressionType t=opt.parameters().constLast();
0639                             
0640                             t.addAssumptions(assumptions);
0641                             
0642                             ret.addAlternative(t.starsToType(starToType));
0643                         }
0644                     }
0645                     
0646                     if(exit)
0647                         break;
0648                 }
0649                 
0650                 if(ret.alternatives().isEmpty()) {
0651 //                     qDebug() << "peee" << c->toString() << signature << exps;
0652                     
0653                     current=ExpressionType(ExpressionType::Error);
0654                     addError(QCoreApplication::tr("Could not call '%1'").arg(c->toString()));
0655                 } else
0656                     current=ret;
0657             }
0658         } break;
0659         default:
0660             current=solve(&o, c->values());
0661             if(current.type()==ExpressionType::Error)
0662                 addError(QCoreApplication::tr("Could not solve '%1'").arg(c->toString()));
0663             break;
0664     }
0665     
0666     current.removeAssumptions(c->bvarStrings());
0667     
0668     m_typeForBVar=ctx;
0669     
0670     if(current.type()==ExpressionType::Many && current.alternatives().size()==1) {
0671         current=current.alternatives().at(0);
0672     }
0673     
0674     return QString();
0675 }
0676 
0677 QVariant ExpressionTypeChecker::visit(const CustomObject*)
0678 {
0679     Q_ASSERT(false && "we shouldn't have to construct any custom object");
0680     return QString();
0681 }
0682 
0683 ExpressionType ExpressionTypeChecker::tellTypeIdentity(const QString& name, const ExpressionType& type)
0684 {
0685     QList<ExpressionType> opts=type.type()==ExpressionType::Many ? type.alternatives() : QList<ExpressionType>() << type;
0686     
0687     for(QList< ExpressionType >::iterator it=opts.begin(), itEnd=opts.end(); it!=itEnd; ++it) {
0688         QMap< QString, ExpressionType >::const_iterator itFound=it->assumptions().constFind(name);
0689         
0690         if(itFound!=it->assumptions().constEnd()) {
0691             QList<ExpressionType> optsFound=itFound->type()==ExpressionType::Many ? itFound->alternatives() : QList<ExpressionType>() << *itFound;
0692             for(QList< ExpressionType >::iterator itf=optsFound.begin(), itfEnd=optsFound.end(); itf!=itfEnd; ++itf) {
0693                 if(!itf->canReduceTo(type)) {
0694 //                     qDebug() << "incoherent type" << *itf << type;
0695                     addError(QCoreApplication::tr("Incoherent type for the variable '%1'").arg(name));
0696                     break;
0697                 }
0698                 QMap<int, ExpressionType> stars;
0699                 stars=ExpressionType::computeStars(stars, *itf, *it);
0700 //                 qDebug() << "fiiiiiiiii" << stars  << "\n\t" << *it << "\n\t" << *itFound;
0701                 *it=it->starsToType(stars);
0702             }
0703         }
0704     }
0705     return ExpressionType(ExpressionType::Many, opts);
0706 }
0707 
0708 //1. Check if parameters are applied correctly
0709 //2. Return the operator result type
0710 QVariant ExpressionTypeChecker::visit(const Container* c)
0711 {
0712 //     qDebug() << "XIUXIU" << c->toString();
0713     switch(c->containerType()) {
0714         case Container::piecewise: {
0715             ExpressionType type=commonType(c->m_params);
0716             
0717             if(type.isError()) {
0718                 addError(QCoreApplication::tr("Could not determine the type for piecewise"));
0719                 current=type;
0720             } else {
0721                 QList<ExpressionType> alts=type.type()==ExpressionType::Many ? type.alternatives() : QList<ExpressionType>() << type, alts2;
0722                 
0723                 for(QList< ExpressionType >::iterator it=alts.begin(), itEnd=alts.end(); it!=itEnd; ++it) {
0724                     QMap<QString, ExpressionType> assumptions=typeIs(c->constBegin(), c->constEnd(), *it);
0725                     
0726     //                 QMap<int, ExpressionType> stars;
0727     //                 bool b=ExpressionType::matchAssumptions(&stars, assumptions, type.assumptions());
0728     //                 Q_ASSERT(b);
0729     //                 type=type.starsToType(stars);
0730                     
0731 //                     qDebug() << "suuuuu\n\t" << it->assumptions() << "\n\t" << assumptions;
0732                     QMap<int, ExpressionType> stars;
0733                     bool b=ExpressionType::matchAssumptions(&stars, it->assumptions(), assumptions);
0734                     b&=ExpressionType::assumptionsMerge(it->assumptions(), assumptions);
0735 //                     qDebug() << "fefefe" << b << it->assumptions();
0736                     
0737                     if(b) {
0738                         alts2 += *it;
0739 //                         qDebug() << "!!!" << it->assumptions() << b;
0740                     }
0741                 }
0742                 current=ExpressionType(ExpressionType::Many, alts2);
0743             }
0744             
0745         }    break;
0746         case Container::piece: {
0747             QMap<QString, ExpressionType> assumptions=typeIs(c->m_params.constLast(), ExpressionType(ExpressionType::Bool)); //condition check
0748             c->m_params.first()->accept(this); //we return the body
0749             QList<ExpressionType> alts=current.type()==ExpressionType::Many ? current.alternatives() : QList<ExpressionType>() << current, rets;
0750             foreach(const ExpressionType& t, alts) {
0751                 QMap<int, ExpressionType> stars;
0752                 ExpressionType toadd=t;
0753                 bool b=ExpressionType::assumptionsMerge(toadd.assumptions(), assumptions);
0754                 
0755                 b&=ExpressionType::matchAssumptions(&stars, assumptions, t.assumptions());
0756                 
0757                 if(b) {
0758                     toadd=toadd.starsToType(stars);
0759                     
0760                     rets += toadd;
0761                 }
0762             }
0763             current=ExpressionType(ExpressionType::Many, rets);
0764         }    break;
0765         case Container::declare:{
0766             Q_ASSERT(c->m_params.first()->type()==Object::variable);
0767             Ci* var = static_cast<Ci*>(c->m_params.first());
0768             
0769             m_calculating.append(var->name());
0770             c->m_params.constLast()->accept(this);
0771             m_calculating.removeLast();
0772             
0773             current=tellTypeIdentity(var->name(), current);
0774         }    break;
0775         case Container::lambda: {
0776             QSet<QString> aux=m_lambdascope;
0777             QStringList bvars=c->bvarStrings();
0778             m_lambdascope+=QSet<QString>(bvars.begin(), bvars.end());
0779             c->m_params.constLast()->accept(this);
0780             m_lambdascope=aux;
0781             
0782             QList<ExpressionType> alts=current.type()==ExpressionType::Many ? current.alternatives() : QList<ExpressionType>() << current;
0783             ExpressionType res=ExpressionType(ExpressionType::Many);
0784             foreach(const ExpressionType& alt, alts) {
0785                 QList<ExpressionType> args;
0786                 foreach(const QString& bvar, bvars) {
0787                     ExpressionType toadd;
0788                     if(alt.assumptions().contains(bvar))
0789                         toadd=alt.assumptionFor(bvar);
0790                     else
0791                         toadd=ExpressionType(ExpressionType::Any, m_stars++);
0792                     
0793 //                     qDebug() << "valueee" << bvar << toadd;
0794                     args += toadd;
0795                 }
0796                 args += alt;
0797                 
0798                 args=ExpressionType::lambdaFromArgs(args);
0799                 
0800                 res.addAlternative(ExpressionType(ExpressionType::Many, args));
0801             }
0802             current=res;
0803             current.removeAssumptions(bvars);
0804         }    break;
0805         case Container::otherwise:
0806         case Container::math:
0807         case Container::none:
0808         case Container::downlimit:
0809         case Container::uplimit:
0810         case Container::bvar:
0811         case Container::domainofapplication:
0812 //             for(Container::const_iterator it=c->constBegin(); it!=c->constEnd(); ++it)
0813 //             Q_ASSERT(c->constBegin()+1==c->constEnd());
0814             if(c->constBegin()+1==c->constEnd())
0815                 (*c->constBegin())->accept(this);
0816             break;
0817     }
0818     
0819     if(current.type()==ExpressionType::Many) {
0820         if(current.alternatives().isEmpty())
0821             current=ExpressionType(ExpressionType::Error);
0822         else if(current.alternatives().count()==1)
0823             current=current.alternatives().at(0);
0824     }
0825     
0826     return QString();
0827 }
0828 
0829 template <class T>
0830 QVariant ExpressionTypeChecker::visitListOrVector(const T* v, ExpressionType::Type t, int size)
0831 {
0832     ExpressionType cont=commonType(v->values());
0833     
0834     if(cont.type()==ExpressionType::Many) {
0835         ExpressionType toret(ExpressionType::Many);
0836         foreach(const ExpressionType& contalt, cont.alternatives()) {
0837             QMap<QString, ExpressionType> assumptions;
0838             assumptions=typeIs(v->constBegin(), v->constEnd(), contalt);
0839             ExpressionType cc(t, contalt, size);
0840             
0841             bool b=ExpressionType::assumptionsMerge(cc.assumptions(), assumptions);
0842             if(b)
0843                 toret.addAlternative(cc);
0844         }
0845         
0846         current=toret;
0847     } else if(!cont.isError()) {
0848         QMap<QString, ExpressionType> assumptions=typeIs(v->constBegin(), v->constEnd(), cont);
0849         current=ExpressionType(t, cont, size);
0850         current.addAssumptions(assumptions);
0851     } else
0852         current=ExpressionType(ExpressionType::Error);
0853     
0854     return QString();
0855 }
0856 
0857 QVariant ExpressionTypeChecker::visit(const List* l)
0858 {
0859     visitListOrVector(l, ExpressionType::List, 0);
0860     return QString();
0861 }
0862 
0863 QVariant ExpressionTypeChecker::visit(const Vector* l)
0864 {
0865     visitListOrVector(l, ExpressionType::Vector, l->size());
0866     return QString();
0867 }
0868 
0869 QVariant ExpressionTypeChecker::visit(const Matrix* m)
0870 {
0871     const Matrix* v = m;
0872     ExpressionType::Type t = ExpressionType::Matrix;
0873     int size = m->rowCount();
0874     
0875     QList<Object*> values;
0876     foreach(MatrixRow *row, m->rows())
0877         values.append(row);
0878     
0879     ExpressionType cont=commonType(values);
0880     
0881     if(cont.type()==ExpressionType::Many) {
0882         ExpressionType toret(ExpressionType::Many);
0883         foreach(const ExpressionType& contalt, cont.alternatives()) {
0884             QMap<QString, ExpressionType> assumptions;
0885             assumptions=typeIs(v->constBegin(), v->constEnd(), contalt);
0886             ExpressionType cc(t, contalt, size);
0887             
0888             bool b=ExpressionType::assumptionsMerge(cc.assumptions(), assumptions);
0889             if(b)
0890                 toret.addAlternative(cc);
0891         }
0892         
0893         current=toret;
0894     } else if(!cont.isError()) {
0895         QMap<QString, ExpressionType> assumptions=typeIs(v->constBegin(), v->constEnd(), cont);
0896         current=ExpressionType(t, cont, size);
0897         current.addAssumptions(assumptions);
0898     } else
0899         current=ExpressionType(ExpressionType::Error);
0900     
0901     return QString();
0902 }
0903 
0904 QVariant ExpressionTypeChecker::visit(const MatrixRow* mr)
0905 {
0906     visitListOrVector(mr, ExpressionType::Vector, mr->size());
0907     return QString();
0908 }
0909 
0910 template <class T>
0911 QMap<QString, ExpressionType> ExpressionTypeChecker::typeIs(T it, const T& itEnd, const ExpressionType& type)
0912 {
0913     QList<ExpressionType> types;
0914     for(; it!=itEnd; ++it) {
0915         (*it)->accept(this);
0916         types+=current;
0917     }
0918     types=ExpressionType::manyFromArgs(types);
0919     
0920     bool valid=false;
0921     QMap<QString, ExpressionType> ret;
0922     
0923     foreach(const ExpressionType& tmany, types) {
0924         bool v=true;
0925         QMap<QString, ExpressionType> ret2;
0926         foreach(const ExpressionType& t, tmany.alternatives()) {
0927             v&=inferType(t, type, &ret2);
0928         }
0929         
0930         if(v) {
0931             valid=true;
0932             ExpressionType::assumptionsUnion(ret, ret2);
0933         }
0934     }
0935     
0936     if(!valid)
0937         addError(QCoreApplication::tr("Unexpected type"));
0938     return ret;
0939 }
0940 
0941 QMap<QString, ExpressionType> ExpressionTypeChecker::typeIs(const Object* o, const ExpressionType& type)
0942 {
0943     o->accept(this);
0944 //     qDebug() << "fluuuu" << current << type;
0945     
0946     bool corr=false;
0947     QList<ExpressionType> alts = current.type()==ExpressionType::Many ? current.alternatives() : QList<ExpressionType>() << current;
0948     
0949     QMap<QString, ExpressionType> assumptions(m_typeForBVar);
0950     foreach(const ExpressionType& t, alts) {
0951         QMap<QString, ExpressionType> ass;
0952         bool correct = inferType(t, type, &ass);
0953         if(correct) {
0954             ExpressionType::assumptionsUnion(assumptions, ass);
0955         }
0956         corr|=correct;
0957     }
0958     
0959     if(!corr)
0960         addError(QCoreApplication::tr("Cannot convert '%1' to '%2'").arg(o->toString(), type.toString()));
0961     
0962     return assumptions;
0963 }
0964 
0965 ExpressionType ExpressionTypeChecker::typeForVar(const QString& var)
0966 {
0967     if(m_calculating.contains(var))
0968         return ExpressionType(ExpressionType::Any, m_stars++);
0969     else if(!m_vars.contains(var)) {
0970 //         qDebug() << "checking..." << var;
0971         Q_ASSERT(m_v->contains(var));
0972         m_calculating += var;
0973         m_v->value(var)->accept(this);
0974         m_calculating.removeLast();
0975         current=tellTypeIdentity(var, current);
0976         current.clearAssumptions();
0977         current.simplifyStars();
0978         m_vars[var]=current;
0979 //         qDebug() << "checked type" << var << "=" << current;
0980     }
0981     
0982     ExpressionType ret=m_vars.value(var);
0983     
0984 //     qDebug() << "P/P/P/P/P/" << ret;
0985     m_stars=ret.increaseStars(m_stars);
0986 //     qDebug() << "P/P/P/P/P/" << ret;
0987     return ret;
0988 }
0989 
0990 QStringList ExpressionTypeChecker::errors() const
0991 {
0992     QStringList ret;
0993     foreach(const QStringList& errs, m_err)
0994         ret << errs;
0995     return ret;
0996 }
0997 
0998 void ExpressionTypeChecker::addError(const QString& err)
0999 {
1000     if(m_err.isEmpty())
1001         m_err += QStringList();
1002     
1003     m_err.last().append(err);
1004 }
1005 
1006 void ExpressionTypeChecker::initializeVars(const QMap< QString, ExpressionType >& types)
1007 {
1008     m_vars=types;
1009 }
1010 
1011 QMap<QString, ExpressionType> ExpressionTypeChecker::variablesTypes() const
1012 {
1013     return m_vars;
1014 }
1015 
1016 QVariant ExpressionTypeChecker::visit(const None* ) { Q_ASSERT(false && "should not get here"); return QVariant(); }
1017 
1018 }