WIP: BinSource draft
authorDavid Teller <dteller@mozilla.com>
Thu, 29 Jun 2017 14:07:23 -0700
changeset 641327 9b7dd82d9bc40c62e86a758db99335a66fda7301
parent 641326 4c331720664b137653851efb22f63ab713a6ce4b
child 641328 adc0e0464d77d36790f2ed60d3a4fc47da47a883
push id72504
push userdteller@mozilla.com
push dateSun, 06 Aug 2017 22:28:40 +0000
milestone57.0a1
WIP: BinSource MozReview-Commit-ID: KEnF3oQqr2w
js/src/frontend/BinSource.cpp
--- a/js/src/frontend/BinSource.cpp
+++ b/js/src/frontend/BinSource.cpp
@@ -1,17 +1,18 @@
 #include <mozilla/ArrayUtils.h>
 #include <mozilla/Casting.h>
 #include <mozilla/Maybe.h>
 #include <mozilla/Move.h>
 #include <mozilla/PodOperations.h>
 #include <mozilla/Vector.h>
 
+#include <frontend/Parser.h>
+#include <frontend/ParseNode.h>
 #include <frontend/BinTokenReader.h>
-#include <frontend/ParseNode.h>
 
 
 using namespace mozilla;
 using NameBag = GCHashSet<JSString*>;
 using Names = GCVector<JSString*, 8>;
 
 namespace js {
 namespace frontend {
@@ -37,35 +38,38 @@ const std::string BINJS_VAR_NAME = "BINJ
 const std::string BINJS_LET_NAME = "BINJS:LetDeclaredNames";
 const std::string BINJS_CONST_NAME = "BINJS:ConstDeclaredNames";
 const std::string BINJS_CAPTURED_NAME = "BINJS:CapturedNames";
 const std::string BINJS_DIRECT_EVAL = "BINJS:HasDirectEval";
 
 class ASTReader
 {
 public:
-    bool parse(char* start, char* stop, UniquePtr<ParseNode>& out);
+    bool parse(char* start, char* stop, GlobalSharedContext* sc, UniquePtr<ParseNode>& out);
 private:
     bool raiseError();
 
     // --- Parse full nodes.
 
-    bool parseBool(SimpleTokenReader*, Maybe<bool>*);
-    bool parseProgram(SimpleTokenReader* reader, UniquePtr<ParseNode>& out);
-    bool parseStatement(SimpleTokenReader* reader, UniquePtr<ParseNode>& out);
-    bool parseStatementList(SimpleTokenReader* reader, UniquePtr<ParseNode>& out);
-    bool parseStringList(SimpleTokenReader* reader, MutableHandle<Maybe<Names>> out);
-    bool parseStringSet(SimpleTokenReader* reader, MutableHandle<Maybe<NameBag>>);
+    bool parseBool(SimpleTokenReader*, ParseContext* pc, Maybe<bool>*);
+    bool parseProgram(SimpleTokenReader* reader, ParseContext* pc, UniquePtr<ParseNode>& out);
+    bool parseStatement(SimpleTokenReader* reader, ParseContext* pc, UniquePtr<ParseNode>& out);
+    bool parseStatementList(SimpleTokenReader* reader, ParseContext* pc, UniquePtr<ParseNode>& out);
+    bool parseStringList(SimpleTokenReader* reader, ParseContext* pc, MutableHandle<Maybe<Names>> out);
+    bool parseStringSet(SimpleTokenReader* reader, ParseContext* pc, MutableHandle<Maybe<NameBag>>);
 
     // --- 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, ParseContext* pc, const SimpleTokenReader::Fields* fields, UniquePtr<ParseNode>& out);
+    bool parseExpressionStatementAux(SimpleTokenReader* reader, ParseContext* pc, const SimpleTokenReader::Fields* fields, UniquePtr<ParseNode>& out);
 
     // --- Utilities.
-    bool readString(SimpleTokenReader* reader, MutableHandleString);
+    bool readString(SimpleTokenReader* reader, ParseContext* pc, MutableHandleString);
+
+    const ReadOnlyCompileOptions& options() const;
 
     ParseNodeAllocator allocator;
 
     ParseNode* allocParseNode(size_t size) {
         MOZ_ASSERT(size == sizeof(ParseNode));
         return static_cast<ParseNode*>(allocator.allocNode());
     }
 
@@ -79,30 +83,37 @@ private:
 
     JS_DECLARE_NEW_METHODS(new_, allocParseNode, inline)
 
 private:
     JSContext* cx;
     LifoAlloc& alloc;
 };
 
+
 bool
-ASTReader::parse(char* start, char* stop, UniquePtr<ParseNode>& out) {
+ASTReader::parse(char* start, char* stop, GlobalSharedContext* sc, UniquePtr<ParseNode>& out) {
     SimpleTokenReader reader(this->cx);
     reader.init(start, stop, nullptr);
 
+    Directives directives(options().strictOption);
+    GlobalSharedContext globalsc(this->cx, ScopeKind::Global,
+                                 directives, options().extraWarningsOption);
+    ParseContext globalpc(this, &globalsc, /* newDirectives = */ nullptr);
+
+
     if (!this->parseProgram(&reader, out) || !reader.uninit()) {
         return false;
     }
 
     return true;
 }
 
 bool
-ASTReader::parseProgram(SimpleTokenReader* reader, UniquePtr<ParseNode>& out) {
+ASTReader::parseProgram(SimpleTokenReader* reader, ParseContext* pc, UniquePtr<ParseNode>& out) {
     if (out) {
         // Already parsed.
         return this->raiseError();
     }
     SimpleTokenReader::Fields fields(this->cx);
     SimpleTokenReader sub(this->cx);
 
     std::string name;
@@ -113,26 +124,28 @@ ASTReader::parseProgram(SimpleTokenReade
     if (name != "Program") {
         return false;
     }
 
     return this->parseBlockStatementAux(&sub, &fields, out);
 }
 
 bool
-ASTReader::parseBlockStatementAux(SimpleTokenReader* reader, const SimpleTokenReader::Fields* fields, UniquePtr<ParseNode>& out) {
+ASTReader::parseBlockStatementAux(SimpleTokenReader* reader,
+    ParseContext* pc,
+    const SimpleTokenReader::Fields* fields,
+    UniquePtr<ParseNode>& out)
+{
     UniquePtr<ParseNode> body;
     Maybe<bool> hasDirectEval;
     Rooted<Maybe<Names>> letNames(this->cx);
     Rooted<Maybe<Names>> constNames(this->cx);
     Rooted<Maybe<Names>> varNames(this->cx);
     Rooted<Maybe<NameBag>> capturedNames(this->cx);
 
-    // FIXME: There must be a nicer way to express all of this.
-    // FIXME: Could we somehow generate an optimized parser from the header?
     for (auto field: *fields) {
         // Fields inherited from `BINJS::Scope`.
         // FIXME: We could share this code.
         if (field == BINJS_DIRECT_EVAL) {
             if (!this->parseBool(reader, &hasDirectEval)) {
                 return false;
             }
         } else if (field == BINJS_LET_NAME) {
@@ -169,17 +182,16 @@ ASTReader::parseBlockStatementAux(Simple
             || constNames.get().isNothing()
             || varNames.get().isNothing()
             || capturedNames.get().isNothing()) {
         // FIXME: Once we have headers + header validation, this error check
         // should become an assertion.
         return this->raiseError();
     }
 
-    // FIXME: For the moment, we are conflating `let` and `const`.
     // Probably not a good idea.
     UniquePtr<LexicalScope::Data> bindings(
         NewEmptyBindingData<LexicalScope>(this->cx, this->alloc, letNames->length() + constNames->length())
     );
     if (!bindings) {
         return this->raiseError();
     }
 
@@ -204,17 +216,17 @@ ASTReader::parseBlockStatementAux(Simple
 
     UniquePtr<ParseNode> result(new_<LexicalScopeNode>(bindings.release(), body.release()));
     out = Move(result);
     // FIXME: Validate capturedNames, etc.
     return true;
 }
 
 bool
-ASTReader::parseStringList(SimpleTokenReader* reader, MutableHandle<Maybe<Names>> out) {
+ASTReader::parseStringList(SimpleTokenReader* reader, ParseContext* pc, MutableHandle<Maybe<Names>> out) {
     if (out.get()) {
         return this->raiseError();
     }
     uint32_t length;
     SimpleTokenReader sub(this->cx);
 
     Names result(this->cx);
 
@@ -236,17 +248,17 @@ ASTReader::parseStringList(SimpleTokenRe
         }
     }
 
     out.set(Move(Some(Move(result))));
     return true;
 }
 
 bool
-ASTReader::parseStatementList(SimpleTokenReader* reader, UniquePtr<ParseNode>& out) {
+ASTReader::parseStatementList(SimpleTokenReader* reader, ParseContext* pc, UniquePtr<ParseNode>& out) {
     if (out) {
         return this->raiseError();
     }
     uint32_t length;
     SimpleTokenReader sub(this->cx);
 
     UniquePtr<ParseNode> result(new_<ListNode>(PNK_STATEMENTLIST, TokenPos()));
     if (!result) {
@@ -266,17 +278,17 @@ ASTReader::parseStatementList(SimpleToke
         result->append(statement.release()); // `result` knows how to deallocate `statement`.
     }
 
     result.swap(out);
     return true;
 }
 
 bool
-ASTReader::parseStatement(SimpleTokenReader* reader, UniquePtr<ParseNode>& out) {
+ASTReader::parseStatement(SimpleTokenReader* reader, ParseContext* pc, UniquePtr<ParseNode>& out) {
     if (out) {
         return this->raiseError();
     }
     SimpleTokenReader::Fields fields(this->cx);
     SimpleTokenReader sub(this->cx);
 
     std::string name;
     if (!reader->taggedTuple(&name, &fields, &sub)) {
@@ -344,17 +356,17 @@ ASTReader::parseStatement(SimpleTokenRea
     } else {
         return this->raiseError();
     }
 
     return true;
 }
 
 bool
-ASTReader::parseBool(SimpleTokenReader* reader, Maybe<bool>* result) {
+ASTReader::parseBool(SimpleTokenReader* reader, ParseContext* pc, Maybe<bool>* result) {
     if (result->isSome()) {
         // Already parsed.
         // FIXME: Can replace with an assert once we have
         // implemented headers and header validation.
         return this->raiseError();
     }
     return reader->readBool(result);
 }