WIP: Implemented ForStatement,WhileStatement,DoWhileStatement,TryStatement,ThrowStatement draft
authorDavid Teller <dteller@mozilla.com>
Tue, 25 Jul 2017 13:26:45 +0200
changeset 641340 946967053af70fb85b245a4c3b286f43bf5844b0
parent 641339 e62a6960920252cdeb167c35b5068f10b49f69e8
child 641341 53c8e2509c88095e3f61c8a5c8d62bfaa7700bfb
push id72504
push userdteller@mozilla.com
push dateSun, 06 Aug 2017 22:28:40 +0000
milestone57.0a1
WIP: Implemented ForStatement,WhileStatement,DoWhileStatement,TryStatement,ThrowStatement MozReview-Commit-ID: 8EZQPNtcV1N
js/src/frontend/BinSource.cpp
--- a/js/src/frontend/BinSource.cpp
+++ b/js/src/frontend/BinSource.cpp
@@ -96,18 +96,20 @@ private:
     bool parseExpression(SimpleTokenReader* reader, UniquePtr<ParseNode>& out);
     bool parsePropertyName(SimpleTokenReader* reader, UniquePtr<PropertyName>& out);
     bool parseSwitchCaseList(SimpleTokenReader* reader, UniquePtr<ParseNode>& out);
     bool parseBlockStatement(SimpleTokenReader* reader, UniquePtr<ParseNode>&);
     bool parseCatchClause(SimpleTokenReader* reader, UniquePtr<ParseNode>&);
 
     // --- Parse the contents of a node whose kind has already been determined.
 
-    bool parseBlockStatementAux(SimpleTokenReader* reader, const SimpleTokenReader::Fields* fields, UniquePtr<ParseNode>& out);
-    bool parseExpressionStatementAux(SimpleTokenReader* reader, const SimpleTokenReader::Fields* fields, UniquePtr<ParseNode>& out);
+    bool parseBlockStatementAux(SimpleTokenReader* reader, const std::string& name, const SimpleTokenReader::Fields* fields, UniquePtr<ParseNode>& out);
+    bool parseExpressionStatementAux(SimpleTokenReader* reader, const std::string& name, const SimpleTokenReader::Fields* fields, UniquePtr<ParseNode>& out);
+    bool parseExpressionAux(SimpleTokenReader* reader, const std::string& name, const SimpleTokenReader::Fields* fields, UniquePtr<ParseNode>& out);
+    bool parseVariableDeclarationAux(SimpleTokenReader* reader, const std::string& name, const SimpleTokenReader::Fields* fields, UniquePtr<ParseNode>& out);
 
     // --- Utilities.
     bool readString(SimpleTokenReader* reader, MutableHandleString);
 
     const ReadOnlyCompileOptions& options() const;
 
     ParseNodeAllocator allocator;
 
@@ -170,17 +172,17 @@ ASTReader::parseProgram(SimpleTokenReade
     if (!reader->taggedTuple(&name, &fields, &sub)) {
         return false;
     }
 
     if (name != "Program") {
         return this->raiseError();
     }
 
-    return this->parseBlockStatementAux(&sub, &fields, out);
+    return this->parseBlockStatementAux(&sub, name, &fields, out);
 }
 
 bool
 ASTReader::parseScope(SimpleTokenReader* reader,
     ScopeData& out)
 {
     if (out.hasDirectEval.isSome()
        || out.letNames.address() != nullptr
@@ -236,16 +238,17 @@ ASTReader::parseScope(SimpleTokenReader*
        || out.capturedNames.address() == nullptr) {
            return this->raiseError();
        }
    return true;
 }
 
 bool
 ASTReader::parseBlockStatementAux(SimpleTokenReader* reader,
+    const std::string& name,
     const SimpleTokenReader::Fields* fields,
     UniquePtr<ParseNode>& out)
 {
     UniquePtr<ParseNode> body;
     ScopeData scope(this->cx);
 
     for (auto field: *fields) {
         if (field == BINJS_SCOPE) {
@@ -385,23 +388,23 @@ ASTReader::parseStatement(SimpleTokenRea
     if (name == "EmptyStatement") {
         UniquePtr<ParseNode> result(new_<NullaryNode>(PNK_NOP, TokenPos()));
         if (!result) {
             return false;
         }
         out = Move(result);
     } else if (name == "BlockStatement") {
         UniquePtr<ParseNode> body;
-        if (!this->parseBlockStatementAux(&sub, &fields, body)) {
+        if (!this->parseBlockStatementAux(&sub, name, &fields, body)) {
             return false;
         }
         out = Move(body);
     } else if (name == "ExpressionStatement") {
         UniquePtr<ParseNode> body;
-        if (!this->parseExpressionStatementAux(&sub, &fields, body)) {
+        if (!this->parseExpressionStatementAux(&sub, name, &fields, body)) {
             return false;
         }
         out = Move(body);
     } else if (name == "DebuggerStatement") {
         UniquePtr<ParseNode> result(new_<DebuggerStatement>(TokenPos()));
         if (!result) {
             return false;
         }
@@ -682,22 +685,135 @@ ASTReader::parseStatement(SimpleTokenRea
             return false;
         }
 
         Unused << block.release();
         Unused << handler.release();
         Unused << finalizer.release();
 
         out = Move(result);
-    } else if (name == "WhileStatement") {
-        // FIXME: Implement
-    } else if (name == "DoWhileStatement") {
-        // FIXME: Implement
+
+    } else if (name == "WhileStatement" || name == "DoWhileStatement") {
+
+        UniquePtr<ParseNode> test;
+        UniquePtr<ParseNode> body;
+
+        for (auto field: fields) {
+            if (field == "test") {
+                if (!this->parseExpression(&sub, test)) {
+                    return false;
+                }
+            } else if (field == "body") {
+                if (!this->parseStatement(&sub, test)) {
+                    return false;
+                }
+            } else {
+                return this->raiseError();
+            }
+        }
+
+        if (!test || !body) {
+            return this->raiseError();
+        }
+
+        if (name == "WhileStatement") {
+            UniquePtr<ParseNode> result(new_<BinaryNode>(PNK_WHILE, JSOP_NOP, TokenPos(), body.get(), test.get()));
+
+            if (!result) {
+                return false;
+            }
+            out = Move(result);
+        } else {
+            UniquePtr<ParseNode> result(new_<BinaryNode>(PNK_DOWHILE, JSOP_NOP, TokenPos(), body.get(), test.get()));
+
+            if (!result) {
+                return false;
+            }
+            out = Move(result);
+        }
+
+        Unused << test.release();
+        Unused << body.release();
+
     } else if (name == "ForStatement") {
-        // FIXME: Implement
+
+        UniquePtr<ParseNode> init; // Optional
+        UniquePtr<ParseNode> test; // Optional
+        UniquePtr<ParseNode> update; // Optional
+        ScopeData scope(this->cx); // Optional
+        UniquePtr<ParseNode> body; // Required
+
+        for (auto field: fields) {
+            if (field == "init") {
+
+                // This can be either a VarDecl or an Expression.
+                SimpleTokenReader::Fields subFields(this->cx);
+                SimpleTokenReader subSub(this->cx);
+                std::string subName;
+
+                if (!sub.taggedTuple(&subName, &subFields, &subSub)) {
+                    return false;
+                }
+
+
+                if (subName == "VariableDeclaration") {
+                    if (!this->parseVariableDeclarationAux(&subSub, subName, &subFields, init)) {
+                        return false;
+                    }
+                } else /* Parse as expression */ {
+                    if (!this->parseExpressionAux(&subSub, subName, &subFields, init)) {
+                        return false;
+                    }
+                }
+
+            } else if (field == "test") {
+                if (!this->parseExpression(&sub, test)) {
+                    return false;
+                }
+            } else if (field == "update") {
+                if (!this->parseExpression(&sub, update)) {
+                    return false;
+                }
+            } else if (field == BINJS_SCOPE) {
+                if (!this->parseScope(&sub, scope)) {
+                    return false;
+                }
+            } else if (field == "body") {
+                if (!this->parseStatement(&sub, body)) {
+                    return false;
+                }
+            } else {
+                return this->raiseError();
+            }
+        }
+
+        if (!body) {
+            return this->raiseError();
+        }
+
+        UniquePtr<ParseNode> forHead(new_<TernaryNode>(PNK_FORHEAD, JSOP_NOP, init.get(), test.get(), update.get(), TokenPos()));
+        if (!forHead) {
+            return false;
+        }
+        Unused << init.release();
+        Unused << update.release();
+        Unused << test.release();
+
+        UniquePtr<ParseNode> result(new_<BinaryNode>(PNK_FOR, JSOP_NOP, TokenPos(),
+                                          forHead.get(), body.get()));
+
+        if (!result) {
+            return false;
+        }
+
+        Unused << forHead.release();
+        Unused << body.release();
+
+        out = Move(result);
+
     } else if (name == "ForInStatement") {
         // FIXME: Implement
     } else if (name == "FunctionDeclaration") {
         // FIXME: Implement
     } else if (name == "VariableDeclaration") {
         // FIXME: Implement
     } else if (name == "SwitchStatement") {
         // FIXME: Implement