File indexing completed on 2024-05-12 03:42:00

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 "typechecktest.h"
0020 
0021 #include <QTest>
0022 #include <cmath>
0023 #include "expression.h"
0024 #include <expressiontypechecker.h>
0025 #include <analyzer.h>
0026 
0027 QTEST_MAIN( TypeCheckTest )
0028 
0029 using namespace Analitza;
0030 
0031 TypeCheckTest::TypeCheckTest(QObject* parent)
0032     : QObject(parent)
0033     , v(new Analitza::Variables)
0034 {
0035     v->modify(QStringLiteral("fnum"), Expression(QStringLiteral("x->3")));
0036     v->modify(QStringLiteral("fplus"), Expression(QStringLiteral("x->x+x")));
0037     v->modify(QStringLiteral("tovector"), Expression(QStringLiteral("x->vector{x,x}")));
0038     v->modify(QStringLiteral("fnull"), Expression(QStringLiteral("x->x")));
0039     v->modify(QStringLiteral("number"), Expression(QStringLiteral("3")));
0040     v->modify(QStringLiteral("fwrong"), Expression(QStringLiteral("x->piecewise { 1>2 ? fwrong(x), ?fwrong(x+1) }")));
0041 //     v->modify("frec", Expression("x->piecewise { 3>3? frec(x-1), ? 1}"));
0042     v->modify(QStringLiteral("frec"), Expression(QStringLiteral("x->piecewise { frec(cos(x))>3? 2, ? 1}")));
0043     v->modify(QStringLiteral("fact"), Expression(QStringLiteral("n->piecewise { n=1?1, ? n*fact(n-1) }")));
0044     v->modify(QStringLiteral("golambda"), Expression(QStringLiteral("(func, param)->func(param)")));
0045     v->modify(QStringLiteral("gonum"), Expression(QStringLiteral("func->func(1, 2)"))); // (num -> num -> a) -> a
0046     v->modify(QStringLiteral("valid"), Expression(QStringLiteral("a->true"))); // (num -> num -> a) -> a
0047     
0048     v->modify(QStringLiteral("fib"), Expression(QStringLiteral("n->piecewise { eq(n,0)?0, eq(n,1)?1, ?fib(n-1)+fib(n-2) }")));
0049     v->modify(QStringLiteral("fv"), Expression(QStringLiteral("vector{x->sin(x), x->cos(x)}")));
0050     v->modify(QStringLiteral("rtail"), Expression(QStringLiteral("(elems,i)->piecewise { card(elems)>=i ? union(list{elems[i]}, rtail(elems, i+1)), ? list{} }")));
0051     v->modify(QStringLiteral("tail"), Expression(QStringLiteral("elems->rtail(elems,1)")));
0052     v->modify(QStringLiteral("foldr"), Expression(QStringLiteral("(f,z,elems)->piecewise {card(elems)=0 ? z, ? f(elems[1], foldr(f, z, tail(elems))) }")));
0053     v->modify(QStringLiteral("foldl"), Expression(QStringLiteral("(f,z,xs)->piecewise{ card(xs)<=0? z, ? foldl(f, f(z, xs[1]), tail(xs)) }")));
0054     v->modify(QStringLiteral("twoargs"), Expression(QStringLiteral("(x,y)->sin(x)+y")));
0055 }
0056 
0057 TypeCheckTest::~TypeCheckTest()
0058 {
0059     delete v;
0060 }
0061 
0062 void TypeCheckTest::testConstruction_data()
0063 {
0064     QTest::addColumn<QString>("input");
0065     QTest::addColumn<QString>("output");
0066     
0067     QTest::newRow("addition") << "2+4" << "num";
0068     QTest::newRow("tovector") << "tovector" << "a -> <a,2>";
0069     QTest::newRow("vectorcall") << "tovector(3)" << "<num,2>";
0070     QTest::newRow("list+vector") << "list{tovector(3)}" << "[<num,2>]";
0071     QTest::newRow("additionvec") << "vector{2,2}+vector{2,2}" << "<num,2>";
0072     QTest::newRow("sum") << "sum(x : x=1..3)" << "num";
0073     QTest::newRow("sumvec") << "sum(vector{x,x} : x=1..3)" << "<num,2>";
0074     QTest::newRow("sumvec2") << "sum(x : x=vector{1,1}..vector{3,3})" << "<num,2>";
0075     QTest::newRow("vector") << "vector {2,2}" << "<num,2>";
0076     QTest::newRow("list") << "list {2,2}" << "[num]";
0077     QTest::newRow("direct") << "(x->x)(3)" << "num";
0078     QTest::newRow("lambda") << "fnum" << "a -> num";
0079     QTest::newRow("call") << "fnum(3)" << "num";
0080     QTest::newRow("plus") << "fplus" << "(num -> num) | (<num,-1> -> <num,-1>) | ({num,-1x-2} -> {num,-1x-2})";
0081     QTest::newRow("call plus") << "fplus(3)" << "num";
0082     QTest::newRow("call plus vect") << "fplus(vector{3})" << "<num,1>";
0083     QTest::newRow("vec to vec") << "tovector(vector{3})" << "<<num,1>,2>";
0084     QTest::newRow("piecewise") << "piecewise { number=3? 3, ?2 }" << "num";
0085     QTest::newRow("selector") << "selector(2, vector{3, 3})" << "num";
0086     QTest::newRow("selector1") << "selector(2, vector{vector{3}, vector{3}})" << "<num,1>";
0087     QTest::newRow("selectorlist") << "selector(2, list{3, 3})" << "num";
0088     
0089     QTest::newRow("rec") << "frec" << "num -> num";
0090     QTest::newRow("infinite") << "piecewise { 2=3? frec(3), ? 3}" << "num";
0091     QTest::newRow("infinite_1") << "piecewise { 2=3? 3, ? frec(3)}" << "num";
0092     QTest::newRow("fact") << "fact(4)" << "num";
0093     QTest::newRow("factdef") << "fact" << "num -> num";
0094     QTest::newRow("deriv") << "(diff(x:x))(2)" << "num";
0095     QTest::newRow("derivdiff") << "diff(x:x)" << "num -> num";
0096     
0097     QTest::newRow("infer_unary") << "n->cos(n)" << "num -> num";
0098     QTest::newRow("infer") << "n->n=1" << "num -> bool";
0099     QTest::newRow("siplambda") << "func->func(2)" << "(num -> a) -> a";
0100     QTest::newRow("numlambda") << "(func, x)->cos(func(x))" << "(a -> num) -> a -> num";
0101     QTest::newRow("golambda")  << "golambda" << "(a -> b) -> a -> b";
0102     QTest::newRow("golambda1") << "golambda(x->x, 1)" << "num";
0103     QTest::newRow("golambda2") << "golambda(x->x, vector{1})" << "<num,1>";
0104     QTest::newRow("golambda3") << "golambda(x->list{x}, 1)" << "[num]";
0105     QTest::newRow("golambda4") << "golambda(x->list{x}, vector{1})" << "[<num,1>]";
0106     
0107     QTest::newRow("fib") << "fib" << "num -> num";
0108     QTest::newRow("equation") << "x+cos(x)" << "num";
0109 //     QTest::newRow("long") << "(c, c1, c2, t1, t2)->(t2-t1)/(c2-c1)a(c-c1)+t1" << "num -> num -> num -> num -> num -> num";
0110     QTest::newRow("selec_call") << "(selector(1, fv))(1)" << "num";
0111     QTest::newRow("selec") << "selector(1, fv)" << "num -> num";
0112     
0113     QTest::newRow("piece") << "x->piecewise { gt(x,0) ? x, ? x+1 }" << "num -> num";
0114     QTest::newRow("parametric") << "t->vector{t,t^2}" << "(num -> <num,2>) | ({num,-1x-1} -> <{num,-1x-1},2>)";
0115     QTest::newRow("somelist") << "t->list{t,t^2}" << "(num -> [num]) | ({num,-1x-1} -> [{num,-1x-1}])";
0116     QTest::newRow("x->piece") << "x->piecewise { gt(x,0) ? selector(1, vector{x, 1/x}),"
0117                                     "? selector(2, vector{x, 1/x} ) }" << "num -> num";
0118     QTest::newRow("div") << "v->selector(1, v)/selector(2, v)" << "(<num,-1> -> num) | (<<num,-1>,-1> -> <num,-1>) | ([num] -> num) | ([<num,-1>] -> <num,-1>) | ({num,-2x-1} -> <num,-1>)";
0119     
0120     QTest::newRow("selec_cos") << "v->cos(selector(1, v))" << "(<num,-1> -> num) | ([num] -> num)";
0121     QTest::newRow("shadowed_param") << "fv->cos(fv)" << "num -> num";
0122     QTest::newRow("eq") << "x->eq(1,x)" << "num -> bool";
0123     QTest::newRow("list@sum") << "v->sum(i^2 : i@v)" << "([num] -> num) | (<num,-1> -> num) | ({num,-3x-2} -> num) | ([{num,-1x-1}] -> {num,-1x-1}) | (<{num,-1x-1},-1> -> {num,-1x-1}) | ({{num,-1x-1},-3x-2} -> {num,-1x-1})";
0124     
0125     QTest::newRow("bounded sum_up") << "n->sum(x : x=n..0)" << "num -> num";
0126     QTest::newRow("bounded sum_down") << "n->sum(x : x=0..n)" << "num -> num";
0127     QTest::newRow("exists") << "exists(l : l@list{true,false,false})" << "bool";
0128     QTest::newRow("existslambda") << "x->sum(l : l@list{true,x,false})" << "bool -> bool";
0129     
0130     QTest::newRow("unknown") << "w" << "a";
0131     
0132     QTest::newRow("gonum") << "gonum((x,y)->x*y)" << "num";
0133     
0134     QTest::newRow("selec_cond") << "xs->piecewise {card(xs)=0? xs}" << "([a] -> [a]) | (<a,-1> -> <a,-1>)";
0135     QTest::newRow("justlambda") << "(f,e)->f(f(e))" << "(a -> a) -> a -> a";
0136     
0137     QTest::newRow("tail") << "ptail:=(elems,i)->piecewise { card(elems)>=i ? union(list{elems[i]}, ptail(elems, i+1)), ? list{} }"
0138                         << "(<a,-1> -> num -> [a]) | ([a] -> num -> [a])";
0139     QTest::newRow("tail1") << "(elems,i)->list{elems[i]}" << "(<a,-1> -> num -> [a]) | ([a] -> num -> [a]) | ({a,-2x-1} -> num -> [<a,-1>])";
0140     QTest::newRow("tailp") << "(elems,i)->piecewise{ card(elems)>=i ? list{elems[i]}, ? list{}}" << "(<a,-1> -> num -> [a]) | ([a] -> num -> [a])";
0141     QTest::newRow("tail3") << "(elems,i)->union(list{elems[i]}, list{})" << "(<a,-1> -> num -> [a]) | ([a] -> num -> [a]) | ({b,-2x-1} -> num -> [<b,-1>])";
0142     QTest::newRow("tail4") << "ptail:=(elems,i)->union(list{elems[i]}, ptail(elems, i))" << "(<a,-1> -> num -> [a]) | ([a] -> num -> [a]) | ({b,-2x-1} -> num -> [<b,-1>])";
0143 //     QTest::newRow("tail5") << "(elems,i)->list{list{elems[i]}, ptail(elems, i)}" << "(<a,-1> -> num -> [a]) | ([a] -> num -> [a])";
0144     QTest::newRow("tail6") << "tail" << "(<a,-1> -> [a]) | ([a] -> [a])";
0145     
0146     QTest::newRow("pe") << "vector{x->x, x->x+2}" << "<(num -> num),2>";
0147     QTest::newRow("ana") << "f:=o->vector { x->x+o, x->x*o }" << "(num -> <(num -> num),2>) | (<num,-1> -> <(<num,-1> -> <num,-1>),2>) | ({num,-1x-2} -> <({num,-1x-2} -> {num,-1x-2}),2>)";
0148     QTest::newRow("pp") << "(x,f)->list{ f(x), cos(x) }" << "num -> (num -> num) -> [num]";
0149     QTest::newRow("pp1") << "(x,f)->list{ cos(x), f(x) }" << "num -> (num -> num) -> [num]";
0150     
0151     QTest::newRow("foldl") << "foldl"
0152                         << "((a -> b -> a) -> a -> <b,-1> -> a) | ((a -> b -> a) -> a -> [b] -> a)";
0153 //     QTest::newRow("foldl1") << "foldl1:=(f,z,xs)->piecewise{ card(xs)>0? foldl1(f, f(z, xs[1]), tail(xs)), ? z }"
0154 //                         << "((a -> b -> a) -> a -> <b,-1> -> a) | ((a -> b -> a) -> a -> [b] -> a)";
0155     QTest::newRow("foldl2") << "foldl2:=(f,z,xs)->piecewise{ card(xs)>0? foldl2(f, f(z, xs[1]), tail(xs)), ? cos(z) }"
0156                         << "((num -> a -> num) -> num -> <a,-1> -> num) | ((num -> a -> num) -> num -> [a] -> num)";
0157     QTest::newRow("foldl3") << "foldl3:=(f,z,xs)->foldl3(f, f(z, xs[1]), tail(xs))" << "((a -> b -> a) -> a -> <b,-1> -> c) | ((a -> b -> a) -> a -> [b] -> c)";
0158     
0159     QTest::newRow("foldr") << "(f,z,elems)->piecewise {card(elems)=0 ? z, ? f(elems[1], foldr(f, z, tail(elems))) }"
0160                                 << "((a -> b -> b) -> b -> <a,-1> -> b) | ((a -> b -> b) -> b -> [a] -> b)";
0161     QTest::newRow("foldr_call") << "foldr"
0162                                 << "((a -> b -> b) -> b -> <a,-1> -> b) | ((a -> b -> b) -> b -> [a] -> b)";
0163     QTest::newRow("foldr1") << "foldr1:=(f,elems)->piecewise {card(elems)=1 ? elems[1], ? f(elems[1], foldr1(f, elems)) }"
0164                                 << "((a -> a -> a) -> <a,-1> -> a) | ((a -> a -> a) -> [a] -> a)";
0165     QTest::newRow("foldr11") << "(f,elems)->f(elems[1], f(elems[2], elems[3]))" << "((a -> a -> a) -> <a,-1> -> a) | ((a -> a -> a) -> [a] -> a) | ((<b,-1> -> <b,-1> -> <b,-1>) -> {b,-2x-1} -> a)";
0166     QTest::newRow("foldr2") << "(f,elems)->f(elems[1], elems[2])" << "((a -> a -> b) -> <a,-1> -> b) | ((a -> a -> b) -> [a] -> b) | ((<a,-1> -> <a,-1> -> b) -> {a,-2x-1} -> b)";
0167     QTest::newRow("foldr3") << "(f,elems)->f(elems[1])" << "((a -> b) -> <a,-1> -> b) | ((a -> b) -> [a] -> b) | ((<a,-1> -> b) -> {a,-2x-1} -> b)";
0168     QTest::newRow("foldr4") << "(f,elems)->f(cos(elems[1]))" << "((num -> a) -> <num,-1> -> a) | ((num -> a) -> [num] -> a)";
0169     QTest::newRow("foldr5") << "(f,elems)->f(f(elems[1]))" << "((a -> a) -> <a,-1> -> a) | ((a -> a) -> [a] -> a) | ((<b,-1> -> <b,-1>) -> {b,-2x-1} -> a)";
0170     QTest::newRow("foldr6") << "(f,elems)->piecewise {card(elems)=1 ? cos(elems[1]), ? f(elems) }"
0171                                 << "((<num,-1> -> num) -> <num,-1> -> num) | (([num] -> num) -> [num] -> num)";
0172     
0173     QTest::newRow("filter")  << "(condition,elems)->foldr((v,pred)->piecewise{ condition(v) ? union(list{v}, pred), ? pred }, list{}, elems)"
0174                                 << "((a -> bool) -> <a,-1> -> [a]) | ((a -> bool) -> [a] -> [a])";
0175     
0176     QTest::newRow("arg") << "c->arctan(c[2]/c[1])" << "(<num,-1> -> num) | ([num] -> num)";
0177     QTest::newRow("rect") << "v->v[1]*cos(v[2])" << "(<num,-1> -> num) | ([num] -> num)";
0178     QTest::newRow("crash") << "u->(v->vector { v[2] })((v->vector { v[2] })(u))" << "(<a,1> -> <a,1>) | ([a] -> <a,1>) | ({a,-2x1} -> <<a,1>,1>)";
0179     
0180     QTest::newRow("scopes") << "or((x->list{}=x)(list{}), (x->x=0)(0))" << "bool";
0181     
0182     QTest::newRow("unify") << "t->vector { 1, times(2, 3, t) }" << "num -> <num,2>";
0183     
0184     QTest::newRow("nary") << "l->and(l=3, l=3, l=3)" << "num -> bool";
0185     QTest::newRow("nary1") << "l->and(valid(l), l=3, l=3)" << "num -> bool";
0186     QTest::newRow("nary2") << "l->and(l=3, l=3, valid(l))" << "num -> bool";
0187     
0188     QTest::newRow("matrix") << "matrix { matrixrow { 1 } }" << "{num,1x1}";
0189     QTest::newRow("matrix2r") << "matrix { matrixrow { 1 }, matrixrow { 2 } }" << "{num,2x1}";
0190     QTest::newRow("matrix2c") << "matrix { matrixrow { 1, 2 } }" << "{num,1x2}";
0191     QTest::newRow("matrix+") << "matrix { matrixrow { 1 }, matrixrow { 2 } }+matrix { matrixrow { 1 }, matrixrow { 2 } }" << "{num,2x1}";
0192     QTest::newRow("matrix_selector0") << "selector(1, matrix { matrixrow { 1 }, matrixrow { 2 } })" << "<num,1>";
0193     QTest::newRow("matrix_selector1") << "selector(1, selector(1, matrix { matrixrow { 1 }, matrixrow { 2 } }))" << "num";
0194     QTest::newRow("matrix_transpose") << "transpose( matrix { matrixrow { 1, 2 } })" << "{num,2x1}";
0195 }
0196 
0197 void TypeCheckTest::testConstruction()
0198 {
0199     QFETCH(QString, input);
0200     QFETCH(QString, output);
0201     
0202     Expression e(input);
0203     if(!e.isCorrect()) qDebug() << "errors: " << e.error();
0204     QVERIFY(e.isCorrect());
0205     ExpressionTypeChecker t(v);
0206     
0207     ExpressionType type=t.check(e);
0208     if(!t.isCorrect()) qDebug() << "errors: " << t.errors();
0209     
0210     QVERIFY(t.isCorrect());
0211     QCOMPARE(type.simplifyStars().toString(), output);
0212 }
0213 
0214 void TypeCheckTest::testUncorrection()
0215 {
0216     QFETCH(QString, input);
0217     
0218     Expression e(input);
0219     if(!e.isCorrect())
0220         qDebug() << "wrong exp:" << e.error();
0221     QVERIFY(e.isCorrect());
0222     ExpressionTypeChecker t(v);
0223     
0224     ExpressionType result=t.check(e);
0225     
0226     if(t.isCorrect())
0227         qDebug() << "wrong type:" << result.toString();
0228     QVERIFY(!t.isCorrect());
0229 //     QVERIFY(!t.errors().isEmpty());
0230 }
0231 
0232 void TypeCheckTest::testUncorrection_data()
0233 {
0234     QTest::addColumn<QString>("input");
0235     QTest::addColumn<QString>("output");
0236     
0237     QTest::newRow("consistency vector") << "vector{2, list{2}}";
0238     QTest::newRow("consistency list")   << "list{2, list{2}}";
0239     
0240     QTest::newRow("piecewise result") << "piecewise { 2=3? 3, ?vector{2} }";
0241     QTest::newRow("piecewise condit") << "piecewise { vector{3}? 3, ?2 }";
0242     
0243     QTest::newRow("no operator") << "list { 2,2 }+list{2}";
0244     QTest::newRow("diff vectors") << "vector { 2,2 }+vector { 2 }";
0245     QTest::newRow("diff types") << "list { 2,2 }+vector { 2 }";
0246     QTest::newRow("wrong call") << "(x->x+x)(list{3})";
0247     QTest::newRow("wrong call2") << "fplus(list{3})";
0248     QTest::newRow("wrong call3") << "(x(x^2))^2";
0249     QTest::newRow("wrong bounds") << "sum(x : x=1..vector{3,3})";
0250     QTest::newRow("bounds2") << "sum(x:x@2)";
0251     QTest::newRow("number call") << "number(3)";
0252     QTest::newRow("wrong param count") << "golambda(2)";
0253     QTest::newRow("unresolved operation") << "selector(2,2)";
0254     
0255     QTest::newRow("charvsreal") << "union(\"lalala\", list{1,2,3})";
0256     QTest::newRow("boolvsreal") << "or(true, false)+2";
0257     QTest::newRow("argscount") << "f:=(x,y)->f(x)";
0258     
0259     QTest::newRow("twoargs") << "(x->x(3))((x,y)->x+y)";
0260     QTest::newRow("times") << "x(x+1)";
0261     QTest::newRow("unify") << "min(2, 3, list{})";
0262     
0263     //TODO: Add invalid recursive call
0264 }
0265 
0266 Q_DECLARE_METATYPE(ExpressionType)
0267 
0268 void TypeCheckTest::testReduction()
0269 {
0270     QFETCH(ExpressionType, type);
0271     QFETCH(ExpressionType, reduced);
0272     QFETCH(bool, correct);
0273     
0274     QCOMPARE(type.canReduceTo(reduced), correct);
0275 }
0276 
0277 ExpressionType s(int stars) { return ExpressionType(ExpressionType::Any, stars); }
0278 ExpressionType vec(const ExpressionType& c, int size) { return ExpressionType(ExpressionType::Vector, c, size); }
0279 ExpressionType list(const ExpressionType& c) { return ExpressionType(ExpressionType::List, c); }
0280 ExpressionType val=ExpressionType(ExpressionType::Value);
0281 
0282 void TypeCheckTest::testReduction_data()
0283 {
0284     QTest::addColumn<ExpressionType>("type");
0285     QTest::addColumn<ExpressionType>("reduced");
0286     QTest::addColumn<bool>("correct");
0287     
0288     ExpressionType lambdaStarStar(ExpressionType::Lambda); // a -> a
0289     lambdaStarStar.addParameter(s(1)).addParameter(s(1));
0290     
0291     ExpressionType lambdaNumVector2(ExpressionType::Lambda); // num -> <num, 2>
0292     lambdaNumVector2.addParameter(val).addParameter(vec(val, 2));
0293     
0294     QTest::newRow("sss") << lambdaStarStar << lambdaNumVector2 << false;
0295 }
0296 
0297 class FooCommand : public Analitza::FunctionDefinition
0298 {
0299     virtual Expression operator()(const QList< Expression >&) override
0300     {
0301         return Expression(QStringLiteral("matrix { matrixrow { 8, 9, 0},matrixrow { 7, 5, 3},matrixrow { 1, 2, 10}}"));
0302     }
0303 };
0304 
0305 void TypeCheckTest::testVariadic()
0306 {
0307     QFETCH(QString, expression);
0308     QFETCH(ExpressionType, type);
0309     
0310     Analyzer a(v);
0311     a.builtinMethods()->insertFunction(QStringLiteral("foocommand"), type, new FooCommand);
0312     
0313     a.setExpression(Expression(expression));
0314     
0315     if (a.type() != type.returnValue())
0316         qDebug() << a.type().toString() << type.toString();
0317     QCOMPARE(a.type(), type.returnValue());
0318     
0319     if(!a.isCorrect())
0320         qDebug() << "wrong exp:" << a.errors();
0321     QVERIFY(a.isCorrect());
0322     
0323     Expression result = a.calculate();
0324     
0325     if(!a.isCorrect() || !result.isCorrect())
0326         qDebug() << "errors in calc:" << a.errors() << result.error();
0327     QVERIFY(result.isCorrect());
0328 }
0329 
0330 void TypeCheckTest::testVariadic_data()
0331 {
0332     QTest::addColumn<QString>("expression");
0333     QTest::addColumn<ExpressionType>("type");
0334     
0335     ExpressionType vtype = ExpressionType(ExpressionType::Lambda)
0336     .addParameter(ExpressionType(ExpressionType::Any))
0337     .addParameter(ExpressionType(ExpressionType::Matrix, ExpressionType(ExpressionType::Vector, ExpressionType(ExpressionType::Value), -2), -1));
0338     
0339     QTest::newRow("f1type_alt_1param_ok") << "foocommand(3)" << vtype;
0340     QTest::newRow("f2type_alt_2params_ok") << "foocommand(3,44)" << vtype;
0341     QTest::newRow("f3type_alt_3params_ok") << "foocommand(list{5,6,2},44,vector{3,5})" << vtype;
0342 }
0343 
0344 #include "moc_typechecktest.cpp"