[flang] Message experiment: defer all message generation until non-speculative.
authorpeter klausler <pklausler@nvidia.com>
Fri, 13 Apr 2018 23:00:03 +0000 (16:00 -0700)
committerpeter klausler <pklausler@nvidia.com>
Tue, 17 Apr 2018 23:58:10 +0000 (16:58 -0700)
Original-commit: flang-compiler/f18@b6ce95ca3a6e21a7bfd89afbb522d8a78ebce6c2
Reviewed-on: https://github.com/flang-compiler/f18/pull/59
Tree-same-pre-rewrite: false

flang/lib/parser/basic-parsers.h
flang/lib/parser/debug-parser.h
flang/lib/parser/message.h
flang/lib/parser/parse-state.h
flang/lib/parser/parsing.cc

index d543e55..df7366c 100644 (file)
@@ -78,17 +78,17 @@ public:
   constexpr BacktrackingParser(const BacktrackingParser &) = default;
   constexpr BacktrackingParser(const A &parser) : parser_{parser} {}
   std::optional<resultType> Parse(ParseState *state) const {
-    Messages messages{std::move(*state->messages())};
+    Messages messages{std::move(state->messages())};
     MessageContext context{state->context()};
     ParseState backtrack{*state};
     std::optional<resultType> result{parser_.Parse(state)};
     if (result.has_value()) {
       // preserve any new messages
       messages.Annex(state->messages());
-      state->messages()->swap(messages);
+      state->messages().swap(messages);
     } else {
       state->swap(backtrack);
-      state->messages()->swap(messages);
+      state->messages().swap(messages);
       state->set_context(context);
     }
     return result;
@@ -110,9 +110,9 @@ public:
   constexpr NegatedParser(const NegatedParser &) = default;
   constexpr NegatedParser(const PA &p) : parser_{p} {}
   std::optional<Success> Parse(ParseState *state) const {
-    Messages messages{std::move(*state->messages())};
+    Messages messages{std::move(state->messages())};
     ParseState forked{*state};
-    state->messages()->swap(messages);
+    state->messages().swap(messages);
     if (parser_.Parse(&forked)) {
       return {};
     }
@@ -135,9 +135,9 @@ public:
   constexpr LookAheadParser(const LookAheadParser &) = default;
   constexpr LookAheadParser(const PA &p) : parser_{p} {}
   std::optional<Success> Parse(ParseState *state) const {
-    Messages messages{std::move(*state->messages())};
+    Messages messages{std::move(state->messages())};
     ParseState forked{*state};
-    state->messages()->swap(messages);
+    state->messages().swap(messages);
     if (parser_.Parse(&forked).has_value()) {
       return {Success{}};
     }
@@ -238,47 +238,76 @@ public:
   constexpr AlternativeParser(const AlternativeParser &) = default;
   constexpr AlternativeParser(const PA &pa, const PB &pb) : pa_{pa}, pb_{pb} {}
   std::optional<resultType> Parse(ParseState *state) const {
-    Messages messages{std::move(*state->messages())};
+    Messages messages{std::move(state->messages())};
     MessageContext context{state->context()};
     ParseState backtrack{*state};
+    int depth{state->alternativeDepth()};
+    bool deferred{state->deferMessages()};
+    if (!deferred) {
+      if (depth == 0 && state->messages().empty()) {
+        CHECK(!state->blockedMessages());
+        state->set_deferMessages(true);
+      }
+    }
+    state->set_alternativeDepth(depth + 1);
     if (std::optional<resultType> ax{pa_.Parse(state)}) {
-      // preserve any new messages
-      messages.Annex(state->messages());
-      state->messages()->swap(messages);
+      if (!deferred && state->blockedMessages()) {
+        // We deferred messages but now we need them.  Regenerate.
+        state->swap(backtrack);
+        state->messages().swap(messages);
+        state->set_context(context);
+        return pa_.Parse(state);
+      }
+      state->set_alternativeDepth(depth)
+          .set_deferMessages(deferred)
+          .set_context(context)
+          .messages().Annex(messages);
       return ax;
     }
-#if 0  // needed below if "tied" messages are to be saved
-    auto start = backtrack.GetLocation();
-#endif
-    ParseState paState{std::move(*state)};
+    ParseState backtrack2{backtrack};
     state->swap(backtrack);
-    state->set_context(context);
+    if (!deferred) {
+      if (depth == 0 && state->messages().empty()) {
+        CHECK(!state->blockedMessages());
+        state->set_deferMessages(true);
+      }
+    }
+    state->set_alternativeDepth(depth + 1);
     if (std::optional<resultType> bx{pb_.Parse(state)}) {
-      // preserve any new messages
-      messages.Annex(state->messages());
-      state->messages()->swap(messages);
+      if (!deferred && state->blockedMessages()) {
+        state->swap(backtrack2);
+        state->messages().swap(messages);
+        state->set_context(context);
+        return pb_.Parse(state);
+      }
+      state->set_alternativeDepth(depth)
+          .set_deferMessages(deferred)
+          .set_context(context)
+          .messages().Annex(messages);
       return bx;
     }
     // Both alternatives failed.  Retain the state (and messages) from the
     // alternative parse that went the furthest.
-    auto paEnd = paState.GetLocation();
-    auto pbEnd = state->GetLocation();
-    if (paEnd > pbEnd) {
-      messages.Annex(paState.messages());
-      state->swap(paState);
-    } else if (paEnd < pbEnd) {
-      messages.Annex(state->messages());
+    if (backtrack.GetLocation() >= state->GetLocation()) {
+      if (!deferred && backtrack.blockedMessages()) {
+        state->swap(backtrack2);
+        state->messages().swap(messages);
+        state->set_context(context);
+        return pa_.Parse(state);
+      }
+      state->swap(backtrack);
     } else {
-      // It's a tie.
-      messages.Annex(paState.messages());
-#if 0
-      if (paEnd > start) {
-        // Both parsers consumed text; retain messages from both.
-        messages.Annex(state->messages());
+      if (!deferred && state->blockedMessages()) {
+        state->swap(backtrack2);
+        state->messages().swap(messages);
+        state->set_context(context);
+        return pb_.Parse(state);
       }
-#endif
     }
-    state->messages()->swap(messages);
+    state->set_alternativeDepth(depth)
+        .set_deferMessages(deferred)
+        .set_context(context)
+        .messages().Annex(messages);
     return {};
   }
 
@@ -312,19 +341,19 @@ public:
   constexpr RecoveryParser(const RecoveryParser &) = default;
   constexpr RecoveryParser(const PA &pa, const PB &pb) : pa_{pa}, pb_{pb} {}
   std::optional<resultType> Parse(ParseState *state) const {
-    Messages messages{std::move(*state->messages())};
+    Messages messages{std::move(state->messages())};
     MessageContext context{state->context()};
     ParseState backtrack{*state};
     std::optional<resultType> ax{pa_.Parse(state)};
     messages.Annex(state->messages());
     if (ax.has_value()) {
-      state->messages()->swap(messages);
+      state->messages().swap(messages);
       return ax;
     }
     state->swap(backtrack);
     state->set_context(context);
     std::optional<resultType> bx{pb_.Parse(state)};
-    state->messages()->swap(messages);
+    state->messages().swap(messages);
     if (bx.has_value()) {
       state->set_anyErrorRecovery();
     }
index 4f3d675..a38d834 100644 (file)
@@ -22,7 +22,7 @@ public:
   constexpr DebugParser(const char *str, std::size_t n)
     : str_{str}, length_{n} {}
   std::optional<Success> Parse(ParseState *state) const {
-    const CookedSource &cooked{state->messages()->cooked()};
+    const CookedSource &cooked{state->messages().cooked()};
     if (auto context = state->context()) {
       context->Emit(std::cout, cooked);
     }
index d7892bd..9cfc123 100644 (file)
@@ -189,14 +189,14 @@ public:
     return *last_;
   }
 
-  void Annex(Messages *that) {
-    if (!that->messages_.empty()) {
+  void Annex(Messages &that) {
+    if (!that.messages_.empty()) {
       if (messages_.empty()) {
-        messages_ = std::move(that->messages_);
+        messages_ = std::move(that.messages_);
       } else {
-        messages_.splice_after(last_, that->messages_);
+        messages_.splice_after(last_, that.messages_);
       }
-      last_ = that->last_;
+      last_ = that.last_;
     }
   }
 
index 1a82a68..10216bf 100644 (file)
@@ -35,7 +35,10 @@ public:
       warnOnNonstandardUsage_{that.warnOnNonstandardUsage_},
       warnOnDeprecatedUsage_{that.warnOnDeprecatedUsage_},
       anyErrorRecovery_{that.anyErrorRecovery_},
-      anyConformanceViolation_{that.anyConformanceViolation_} {}
+      anyConformanceViolation_{that.anyConformanceViolation_},
+      alternativeDepth_{that.alternativeDepth_},
+      deferMessages_{that.deferMessages_}, blockedMessages_{
+                                               that.blockedMessages_} {}
   ParseState(ParseState &&that)
     : p_{that.p_}, limit_{that.limit_}, messages_{std::move(that.messages_)},
       context_{std::move(that.context_)}, userState_{that.userState_},
@@ -44,7 +47,10 @@ public:
       warnOnNonstandardUsage_{that.warnOnNonstandardUsage_},
       warnOnDeprecatedUsage_{that.warnOnDeprecatedUsage_},
       anyErrorRecovery_{that.anyErrorRecovery_},
-      anyConformanceViolation_{that.anyConformanceViolation_} {}
+      anyConformanceViolation_{that.anyConformanceViolation_},
+      alternativeDepth_{that.alternativeDepth_},
+      deferMessages_{that.deferMessages_}, blockedMessages_{
+                                               that.blockedMessages_} {}
   ParseState &operator=(ParseState &&that) {
     swap(that);
     return *this;
@@ -58,7 +64,7 @@ public:
     std::memcpy(&that, buffer, bytes);
   }
 
-  Messages *messages() { return &messages_; }
+  Messages &messages() { return messages_; }
 
   bool anyErrorRecovery() const { return anyErrorRecovery_; }
   void set_anyErrorRecovery() { anyErrorRecovery_ = true; }
@@ -105,6 +111,20 @@ public:
     return *this;
   }
 
+  int alternativeDepth() const { return alternativeDepth_; }
+  ParseState &set_alternativeDepth(int d) {
+    alternativeDepth_ = d;
+    return *this;
+  }
+
+  bool deferMessages() const { return deferMessages_; }
+  ParseState &set_deferMessages(bool yes) {
+    deferMessages_ = yes;
+    return *this;
+  }
+
+  bool blockedMessages() const { return blockedMessages_; }
+
   const char *GetLocation() const { return p_; }
 
   MessageContext &PushContext(MessageFixedText text) {
@@ -118,18 +138,30 @@ public:
     }
   }
 
-  Message &Say(MessageFixedText t) { return Say(p_, t); }
-  Message &Say(MessageFormattedText &&t) { return Say(p_, std::move(t)); }
-  Message &Say(MessageExpectedText &&t) { return Say(p_, std::move(t)); }
+  void Say(MessageFixedText t) { return Say(p_, t); }
+  void Say(MessageFormattedText &&t) { return Say(p_, std::move(t)); }
+  void Say(MessageExpectedText &&t) { return Say(p_, std::move(t)); }
 
-  Message &Say(const char *at, MessageFixedText t) {
-    return messages_.Put(Message{at, t, context_});
+  void Say(const char *at, MessageFixedText t) {
+    if (deferMessages_) {
+      blockedMessages_ = true;
+    } else {
+      messages_.Put(Message{at, t, context_});
+    }
   }
-  Message &Say(const char *at, MessageFormattedText &&t) {
-    return messages_.Put(Message{at, std::move(t), context_});
+  void Say(const char *at, MessageFormattedText &&t) {
+    if (deferMessages_) {
+      blockedMessages_ = true;
+    } else {
+      messages_.Put(Message{at, std::move(t), context_});
+    }
   }
-  Message &Say(const char *at, MessageExpectedText &&t) {
-    return messages_.Put(Message{at, std::move(t), context_});
+  void Say(const char *at, MessageExpectedText &&t) {
+    if (deferMessages_) {
+      blockedMessages_ = true;
+    } else {
+      messages_.Put(Message{at, std::move(t), context_});
+    }
   }
 
   bool IsAtEnd() const { return p_ >= limit_; }
@@ -176,6 +208,9 @@ private:
   bool warnOnDeprecatedUsage_{false};
   bool anyErrorRecovery_{false};
   bool anyConformanceViolation_{false};
+  int alternativeDepth_{0};
+  bool deferMessages_{false};
+  bool blockedMessages_{false};
   // NOTE: Any additions or modifications to these data members must also be
   // reflected in the copy and move constructors defined at the top of this
   // class definition!
index 84c4b14..f06fa41 100644 (file)
@@ -82,8 +82,10 @@ void Parsing::Parse() {
       .set_warnOnDeprecatedUsage(options_.isStrictlyStandard)
       .set_userState(&userState);
   parseTree_ = program.Parse(&parseState);
+#if 0 // pmk
   CHECK(
-      !parseState.anyErrorRecovery() || parseState.messages()->AnyFatalError());
+      !parseState.anyErrorRecovery() || parseState.messages().AnyFatalError());
+#endif
   consumedWholeFile_ = parseState.IsAtEnd();
   finalRestingPlace_ = parseState.GetLocation();
   messages_.Annex(parseState.messages());