WIP: Implemented ForInStatement draft
authorDavid Teller <dteller@mozilla.com>
Tue, 25 Jul 2017 13:39:32 +0200
changeset 641341 53c8e2509c88095e3f61c8a5c8d62bfaa7700bfb
parent 641340 946967053af70fb85b245a4c3b286f43bf5844b0
child 641342 8a0ea18ab5c732d5bd0d6bf4761b5f59496f1419
push id72504
push userdteller@mozilla.com
push dateSun, 06 Aug 2017 22:28:40 +0000
milestone57.0a1
WIP: Implemented ForInStatement MozReview-Commit-ID: LHiSWSQ8AQV
js/src/frontend/BinSource.cpp
--- a/js/src/frontend/BinSource.cpp
+++ b/js/src/frontend/BinSource.cpp
@@ -96,16 +96,17 @@ 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 parsePatternAux(SimpleTokenReader* reader, const std::string& name, 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);
 
@@ -805,17 +806,85 @@ ASTReader::parseStatement(SimpleTokenRea
         }
 
         Unused << forHead.release();
         Unused << body.release();
 
         out = Move(result);
 
     } else if (name == "ForInStatement") {
-        // FIXME: Implement
+
+        UniquePtr<ParseNode> left;
+        UniquePtr<ParseNode> right;
+        UniquePtr<ParseNode> body;
+        ScopeData scope(this->cx); // Optional
+
+        for (auto field: fields) {
+            if (field == "left") {
+
+                // This can be either a VarDecl or a Pattern.
+                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, left)) {
+                        return false;
+                    }
+                } else /* Parse as pattern */ {
+                    if (!this->parsePatternAux(&subSub, subName, &subFields, left)) {
+                        return false;
+                    }
+                }
+
+            } else if (field == "right") {
+                if (!this->parseExpression(&sub, right)) {
+                    return false;
+                }
+            } else if (field == "body") {
+                if (!this->parseExpression(&sub, body)) {
+                    return false;
+                }
+            } else if (field == BINJS_SCOPE) {
+                if (!this->parseScope(&sub, scope)) {
+                    return false;
+                }
+            } else {
+                return this->raiseError();
+            }
+        }
+
+        if (!left || !right || !body) {
+            return this->raiseError();
+        }
+
+        UniquePtr<ParseNode> forHead(new_<TernaryNode>(PNK_FORIN, JSOP_NOP, left.get(), nullptr, right.get(), TokenPos()));
+        if (!forHead) {
+            return false;
+        }
+
+        Unused << left.release();
+        Unused << right.release();
+
+        UniquePtr<ParseNode> result(new_<BinaryNode>(PNK_FOR, JSOP_ITER, TokenPos(),
+                                          forHead.get(), body.get()));
+        if (!result) {
+            return false;
+        }
+
+        Unused << forHead.release();
+        Unused << body.release();
+
+        out = Move(result);
+
     } else if (name == "FunctionDeclaration") {
         // FIXME: Implement
     } else if (name == "VariableDeclaration") {
         // FIXME: Implement
     } else if (name == "SwitchStatement") {
         // FIXME: Implement
     } else {
         return this->raiseError();