From kde-commits Wed Sep 30 20:44:34 2015 From: Jan Marker Date: Wed, 30 Sep 2015 20:44:34 +0000 To: kde-commits Subject: [qmlweb/development/qmlweb2] /: [Compiler] Implement loops Message-Id: X-MARC-Message: https://marc.info/?l=kde-commits&m=144364588621992 Git commit 3152b13f9033570a2bd14b4004da21b79f64101e by Jan Marker. Committed on 30/09/2015 at 20:41. Pushed by jangmarker into branch 'development/qmlweb2'. [Compiler] Implement loops * local and global for * local and global for each * while * do while M +43 -0 src/qmljsc/purejavascriptgenerator.cpp M +6 -0 src/qmljsc/purejavascriptgenerator.h A +1 -0 tests/auto/data/javascript/loops.compiled.js A +14 -0 tests/auto/data/javascript/loops.js M +26 -0 tests/auto/qmljsc/testpurejavascriptgenerator.cpp M +5 -4 tests/auto/qmljsc/testpurejavascriptgenerator_integration.cpp http://commits.kde.org/qmlweb/3152b13f9033570a2bd14b4004da21b79f64101e diff --git a/src/qmljsc/purejavascriptgenerator.cpp b/src/qmljsc/purejavasc= riptgenerator.cpp index 0ec9859..ae1fd2e 100644 --- a/src/qmljsc/purejavascriptgenerator.cpp +++ b/src/qmljsc/purejavascriptgenerator.cpp @@ -212,6 +212,13 @@ void PureJavaScriptGenerator::endVisit(AST::CaseBlock = *caseBlock) { m_outputStack << '{' + clausesLeft + defaultClause + clausesRight + '}= '; } = +void PureJavaScriptGenerator::endVisit(AST::DoWhileStatement *) { + const QString expression =3D m_outputStack.pop(); + const QString statement =3D m_outputStack.pop(); + m_outputStack << "do " + statement + "while" + '(' + expression + ')' = + ';'; + // space after do: do var i;while(false); is a valid statement and req= uires a space +} + void PureJavaScriptGenerator::endVisit(AST::CaseClause *) { const QString statement =3D m_outputStack.pop(); const QString expression =3D m_outputStack.pop(); @@ -271,6 +278,21 @@ void PureJavaScriptGenerator::endVisit(AST::FieldMembe= rExpression *fieldMemberEx m_outputStack << objectExpression + '.' + memberName; } = +void PureJavaScriptGenerator::endVisit(AST::ForEachStatement *) { + const QString statement =3D m_outputStack.pop(); + const QString objectExpression =3D m_outputStack.pop(); + const QString variableExpression =3D m_outputStack.pop(); + m_outputStack << "for(" + variableExpression + " in " + objectExpressi= on + ')' + statement; +} + +void PureJavaScriptGenerator::endVisit(AST::ForStatement *forStatement) { + const QString statement =3D m_outputStack.pop(); + const QString incrementExpression =3D (forStatement->expression)?m_out= putStack.pop():""; + const QString condition =3D (forStatement->condition)?m_outputStack.po= p():""; + const QString initialisation =3D (forStatement->initialiser)?m_outputS= tack.pop():""; + m_outputStack << "for(" + initialisation + ';' + condition + ';' + inc= rementExpression + ')' + statement; +} + void PureJavaScriptGenerator::endVisit(AST::FunctionBody *) { const QString body =3D m_outputStack.pop(); m_outputStack << '{' + body + '}'; @@ -298,6 +320,21 @@ void PureJavaScriptGenerator::endVisit(AST::IfStatemen= t *ifExpression) { m_outputStack << code; } = +void PureJavaScriptGenerator::endVisit(AST::LocalForEachStatement *) { + const QString statement =3D m_outputStack.pop(); + const QString objectExpression =3D m_outputStack.pop(); + const QString declaredVariableName =3D m_outputStack.pop(); + m_outputStack << "for(var " + declaredVariableName + " in " + objectEx= pression + ')' + statement; +} + +void PureJavaScriptGenerator::endVisit(AST::LocalForStatement *localForSta= tement) { + const QString statement =3D m_outputStack.pop(); + const QString incrementExpression =3D (localForStatement->expression)?= m_outputStack.pop():""; + const QString condition =3D (localForStatement->condition)?m_outputSta= ck.pop():""; + const QString declaration =3D (localForStatement->declarations)?m_outp= utStack.pop():""; + m_outputStack << "for(" + declaration + ';' + condition + ';' + increm= entExpression + ')' + statement; +} + void PureJavaScriptGenerator::endVisit(AST::NumericLiteral *) { } = @@ -386,6 +423,12 @@ void PureJavaScriptGenerator::endVisit(AST::VariableSt= atement *) { m_outputStack << m_outputStack.pop() + ';'; } = +void PureJavaScriptGenerator::endVisit(AST::WhileStatement *) { + const QString statement =3D m_outputStack.pop(); + const QString expression =3D m_outputStack.pop(); + m_outputStack << "while(" + expression + ')' + statement; +} + void PureJavaScriptGenerator::reduceJumpStatement(const char *keyword, QSt= ringRef label) { QString labelStatementCode(keyword); if (label.length() > 0) { diff --git a/src/qmljsc/purejavascriptgenerator.h b/src/qmljsc/purejavascri= ptgenerator.h index ea64b2f..35dfa35 100644 --- a/src/qmljsc/purejavascriptgenerator.h +++ b/src/qmljsc/purejavascriptgenerator.h @@ -58,14 +58,19 @@ public: virtual void endVisit(QQmlJS::AST::CaseClause *) override; virtual void endVisit(QQmlJS::AST::CaseClauses *) override; virtual void endVisit(QQmlJS::AST::DefaultClause *) override; + virtual void endVisit(QQmlJS::AST::DoWhileStatement *) override; virtual void endVisit(QQmlJS::AST::ElementList *) override; virtual void endVisit(QQmlJS::AST::EmptyStatement *) override; virtual void endVisit(QQmlJS::AST::ExpressionStatement *) override; virtual void endVisit(QQmlJS::AST::FieldMemberExpression *) override; + virtual void endVisit(QQmlJS::AST::ForEachStatement *) override; + virtual void endVisit(QQmlJS::AST::ForStatement *) override; virtual void endVisit(QQmlJS::AST::FunctionBody *) override; virtual void endVisit(QQmlJS::AST::FunctionDeclaration *) override; virtual void endVisit(QQmlJS::AST::IdentifierExpression *) override; virtual void endVisit(QQmlJS::AST::IfStatement *) override; + virtual void endVisit(QQmlJS::AST::LocalForEachStatement *) override; + virtual void endVisit(QQmlJS::AST::LocalForStatement *) override; virtual void endVisit(QQmlJS::AST::NumericLiteral *) override; virtual void endVisit(QQmlJS::AST::ObjectLiteral *) override; virtual void endVisit(QQmlJS::AST::PostDecrementExpression *) override; @@ -83,6 +88,7 @@ public: virtual void endVisit(QQmlJS::AST::VariableDeclaration *) override; virtual void endVisit(QQmlJS::AST::VariableDeclarationList *) override; virtual void endVisit(QQmlJS::AST::VariableStatement *) override; + virtual void endVisit(QQmlJS::AST::WhileStatement *) override; = private: template void reduceListStack(ListType* list, const= char* separator =3D ""); diff --git a/tests/auto/data/javascript/loops.compiled.js b/tests/auto/data= /javascript/loops.compiled.js new file mode 100644 index 0000000..03cae8b --- /dev/null +++ b/tests/auto/data/javascript/loops.compiled.js @@ -0,0 +1 @@ +while(true){;}do {;}while(true);for(i=3D5;i<10;++i);for(var i=3D5;i;++i);f= or(i in o){;}for(var i in o){;} \ No newline at end of file diff --git a/tests/auto/data/javascript/loops.js b/tests/auto/data/javascri= pt/loops.js new file mode 100644 index 0000000..79f39c9 --- /dev/null +++ b/tests/auto/data/javascript/loops.js @@ -0,0 +1,14 @@ +while(true) { + ; +} +do{ + ; +} while(true); +for(i=3D5;i<10;++i); +for(var i=3D5;i;++i); +for(i in o) { + ; +} +for(var i in o) { + ; +} \ No newline at end of file diff --git a/tests/auto/qmljsc/testpurejavascriptgenerator.cpp b/tests/auto= /qmljsc/testpurejavascriptgenerator.cpp index b194a6d..67573fe 100644 --- a/tests/auto/qmljsc/testpurejavascriptgenerator.cpp +++ b/tests/auto/qmljsc/testpurejavascriptgenerator.cpp @@ -178,6 +178,14 @@ public: , m_caseBlockCasesDefaultCases(&m_twoCaseClauses, &m_defaultClause= , &m_twoCaseClauses) , m_caseClause(&m_trueLiteral, &m_threeStatementsList) , m_switchStatement(&m_trueLiteral, &m_caseBlock) + , m_whileStatement(nullptr, nullptr) + , m_doWhileStatement(nullptr, nullptr) + , m_forStatementAllParts(&m_trueLiteral, &m_falseLiteral, &m_trueL= iteral, &m_block) + , m_forStatementNoPart(nullptr, nullptr, nullptr, &m_block) + , m_localForStatementAllParts(&m_twoVarDeclarations, &m_falseLiter= al, &m_trueLiteral, &m_block) + , m_localForStatementNoPart(nullptr, nullptr, nullptr, &m_block) + , m_forEachStatement(&m_trueLiteral, &m_trueLiteral, &m_block) + , m_localForEachStatement(&m_variableDeclarationWithoutAssignment,= &m_trueLiteral, &m_block) { m_elisionsPart2.finish(); m_arrayElementsExp.finish(); @@ -316,6 +324,16 @@ private: AST::CaseClause m_caseClause; AST::SwitchStatement m_switchStatement; = + /* Loops */ + AST::WhileStatement m_whileStatement; + AST::DoWhileStatement m_doWhileStatement; + AST::ForStatement m_forStatementAllParts; + AST::ForStatement m_forStatementNoPart; + AST::LocalForStatement m_localForStatementAllParts; + AST::LocalForStatement m_localForStatementNoPart; + AST::ForEachStatement m_forEachStatement; + AST::LocalForEachStatement m_localForEachStatement; + private slots: void init() { m_generator =3D new PureJavaScriptGenerator(); @@ -398,6 +416,7 @@ private slots: TEST_ENDVISIT_REDUCES(CaseClause , CaseWithStatement , "c= ase exp:stm;" , ({"case", "exp", "stm;"}) , m_caseClause) TEST_ENDVISIT_REDUCES(CaseClauses , TwoClauses , "c= ase e:s;case e2:s2;", ({"case e:s;", "case e2:s2;"}), m_twoCaseClauses) TEST_ENDVISIT_REDUCES(DefaultClause , AnyCase , "d= efault:stm" , ({"default", "stm"}) , m_defaultClause) + TEST_ENDVISIT_REDUCES(DoWhileStatement , AnyCase , "d= o stm;while(e);", ({"stm;", "e"}) , m_doWhileStatement) TEST_ENDVISIT_REDUCES(ElementList , Expression , "e= xpr," , ({"expr"}) , m_arrayElementsExp) TEST_ENDVISIT_REDUCES(ElementList , TwoExpressions , "e= xpr,expr," , ({"expr", "expr"}) , m_arrayElementsExpExp) TEST_ENDVISIT_REDUCES(ElementList , ElisionExpression , "e= lisionexpr," , ({"elision", "expr"}) , m_arrayElementsElisionExp) @@ -406,6 +425,9 @@ private slots: TEST_ENDVISIT_REDUCES(ExpressionStatement , AnyCase , "e= xpression;" , ({"expression"}) , m_expressionStatement) TEST_ENDVISIT_REDUCES(FieldMemberExpression , AnyCase , "o= bj.property" , ({"obj"}) , m_fieldMemberExpression) TEST_ENDVISIT_REDUCES(FormalParameterList , AnyCase , "i= " , ({"i"}) , m_twoParameters) // does n= othing + TEST_ENDVISIT_REDUCES(ForEachStatement , AnyCase , "f= or(i in o)stm;" , ({"i", "o", "stm;"}) , m_forEachStatement) + TEST_ENDVISIT_REDUCES(ForStatement , AllParts , "f= or(i;c;++)stm;" , ({"i", "c", "++", "stm;"}) , m_forStatementAllParts) + TEST_ENDVISIT_REDUCES(ForStatement , NoPart , "f= or(;;)stm;" , ({"stm;"}) , m_forStatementNoPart) TEST_ENDVISIT_REDUCES(FunctionBody , ClosesCorrectly , "{= func}" , ({"func"}) , m_functionBody) TEST_ENDVISIT_REDUCES(FunctionDeclaration , BodyNoParameters , "f= unction i(){body}" , ({"{body}"}) , m_functionDeclarationWitho= utParameters) TEST_ENDVISIT_REDUCES(FunctionDeclaration , BodyParameters , "f= unction i(para){body}", ({"para", "{body}"}) , m_functionDeclarationWithP= arameters) @@ -413,6 +435,9 @@ private slots: TEST_ENDVISIT_REDUCES(IdentifierExpression , AnyCase , "a= bc" , ({"abc"}) , m_identifierExpression) TEST_ENDVISIT_REDUCES(IfStatement , OnlyIf , "i= f(exp)stm;" , ({"exp", "stm;"}) , m_ifStatementWithoutElse) TEST_ENDVISIT_REDUCES(IfStatement , IfElse , "i= f(exp)s;else s;", ({"exp", "s;", "s;"}) , m_ifStatementWithElse) + TEST_ENDVISIT_REDUCES(LocalForEachStatement , AnyCase , "f= or(var i in o)stm;", ({"i", "o", "stm;"}) , m_localForEachStatement) + TEST_ENDVISIT_REDUCES(LocalForStatement , AllParts , "f= or(var i;c;++)stm;", ({"var i", "c", "++", "stm;"}), m_localForStatementAll= Parts) + TEST_ENDVISIT_REDUCES(LocalForStatement , NoPart , "f= or(;;)stm;" , ({"stm;"}) , m_localForStatementNoPart) TEST_ENDVISIT_REDUCES(NumericLiteral , AnyCase , "2= .7" , ({"2.7"}) , m_numericalExpressionPi) TEST_ENDVISIT_REDUCES(ObjectLiteral , AnyCase , "{= properties}" , ({"properties"}) , m_objectLiteral) TEST_ENDVISIT_REDUCES(PostDecrementExpression , AnyCase , "2= .7--" , ({"2.7"}) , m_postDecrementExpression) @@ -437,6 +462,7 @@ private slots: TEST_ENDVISIT_REDUCES(VariableDeclarationList , OneDeclaration , "v= ar e=3D5" , ({"e=3D5"}) , m_twoVarDeclarationsPa= rt2) TEST_ENDVISIT_REDUCES(VariableDeclarationList , ConstDeclaration , "c= onst e=3D5" , ({"e=3D5"}) , m_twoConstDeclarations= Part2) TEST_ENDVISIT_REDUCES(VariableStatement , AnyCase , "x= ;" , ({"x"}) , m_variableStatement) + TEST_ENDVISIT_REDUCES(WhileStatement , AnyCase , "w= hile(e)stm" , ({"e", "stm"}) , m_whileStatement) = TEST_VISIT_BINARYOP_PUTS_ON_STACK(Assign, "=3D") TEST_VISIT_BINARYOP_PUTS_ON_STACK(InplaceAdd, "+=3D") diff --git a/tests/auto/qmljsc/testpurejavascriptgenerator_integration.cpp = b/tests/auto/qmljsc/testpurejavascriptgenerator_integration.cpp index e88c8dd..9ec3227 100644 --- a/tests/auto/qmljsc/testpurejavascriptgenerator_integration.cpp +++ b/tests/auto/qmljsc/testpurejavascriptgenerator_integration.cpp @@ -60,16 +60,16 @@ private: return QString(inputFile.readAll()); } = + void addRowForFile(QString fileName) { + addRowForFileWithCompiled(fileName, fileName); + } + void addRowForFileWithCompiled(QString sourceFileName, QString compile= dFileName) { const QString folder(":/test/%1.js"); QTest::newRow(sourceFileName.toLocal8Bit()) << astForFile(folder.a= rg(sourceFileName)) << fileContent(folder.arg(compiledFileName)); = } = - void addRowForFile(QString fileName) { - addRowForFileWithCompiled(fileName, fileName); - } - void addRowForFileWithCompiled(QString fileName) { addRowForFileWithCompiled(fileName, QString("%1.compiled").arg(fil= eName)); } @@ -92,6 +92,7 @@ private slots: addRowForFileWithCompiled("objectliterals"); addRowForFileWithCompiled("propertyaccess"); addRowForFileWithCompiled("functioncalls"); + addRowForFileWithCompiled("loops"); } = void test_compileJavaScriptFile() {