فهرست منبع

Collapse Sequence into Block. (#927)

Jon Meow 4 سال پیش
والد
کامیت
904774fbb8

+ 2 - 15
executable_semantics/ast/statement.cpp

@@ -78,27 +78,14 @@ void Statement::PrintDepth(int depth, llvm::raw_ostream& out) const {
       }
       break;
     }
-    case Kind::Sequence: {
-      const auto& seq = cast<Sequence>(*this);
-      seq.statement().PrintDepth(depth, out);
-      if (depth < 0 || depth > 1) {
-        out << "\n";
-      } else {
-        out << " ";
-      }
-      if (seq.next()) {
-        (*seq.next())->PrintDepth(depth - 1, out);
-      }
-      break;
-    }
     case Kind::Block: {
       const auto& block = cast<Block>(*this);
       out << "{";
       if (depth < 0 || depth > 1) {
         out << "\n";
       }
-      if (block.sequence()) {
-        (*block.sequence())->PrintDepth(depth, out);
+      for (const auto* statement : block.statements()) {
+        statement->PrintDepth(depth, out);
         if (depth < 0 || depth > 1) {
           out << "\n";
         }

+ 8 - 31
executable_semantics/ast/statement.h

@@ -27,7 +27,6 @@ class Statement {
     VariableDefinition,
     If,
     Return,
-    Sequence,
     Block,
     While,
     Break,
@@ -60,46 +59,24 @@ class Statement {
   SourceLocation source_loc_;
 };
 
-class Sequence : public Statement {
- public:
-  Sequence(SourceLocation source_loc, Nonnull<Statement*> statement,
-           std::optional<Nonnull<Statement*>> next)
-      : Statement(Kind::Sequence, source_loc),
-        statement_(statement),
-        next_(next) {}
-
-  static auto classof(const Statement* stmt) -> bool {
-    return stmt->kind() == Kind::Sequence;
-  }
-
-  auto statement() const -> const Statement& { return *statement_; }
-  auto statement() -> Statement& { return *statement_; }
-  auto next() const -> std::optional<Nonnull<const Statement*>> {
-    return next_;
-  }
-  auto next() -> std::optional<Nonnull<Statement*>> { return next_; }
-
- private:
-  Nonnull<Statement*> statement_;
-  std::optional<Nonnull<Statement*>> next_;
-};
-
 class Block : public Statement {
  public:
-  Block(SourceLocation source_loc, std::optional<Nonnull<Sequence*>> sequence)
-      : Statement(Kind::Block, source_loc), sequence_(sequence) {}
+  Block(SourceLocation source_loc, std::vector<Nonnull<Statement*>> statements)
+      : Statement(Kind::Block, source_loc), statements_(statements) {}
 
   static auto classof(const Statement* stmt) -> bool {
     return stmt->kind() == Kind::Block;
   }
 
-  auto sequence() const -> std::optional<Nonnull<const Sequence*>> {
-    return sequence_;
+  auto statements() const -> llvm::ArrayRef<Nonnull<const Statement*>> {
+    return statements_;
+  }
+  auto statements() -> llvm::MutableArrayRef<Nonnull<Statement*>> {
+    return statements_;
   }
-  auto sequence() -> std::optional<Nonnull<Sequence*>> { return sequence_; }
 
  private:
-  std::optional<Nonnull<Sequence*>> sequence_;
+  std::vector<Nonnull<Statement*>> statements_;
 };
 
 class ExpressionStatement : public Statement {

+ 5 - 8
executable_semantics/interpreter/exec_program.cpp

@@ -23,14 +23,11 @@ static void AddIntrinsics(Nonnull<Arena*> arena,
       arena->New<ExpressionPattern>(
           arena->New<StringTypeLiteral>(source_loc)))};
   auto print_return = arena->New<Block>(
-      source_loc,
-      arena->New<Sequence>(
-          source_loc,
-          arena->New<Return>(source_loc,
-                             arena->New<IntrinsicExpression>(
-                                 IntrinsicExpression::Intrinsic::Print),
-                             false),
-          std::nullopt));
+      source_loc, std::vector<Nonnull<Statement*>>({arena->New<Return>(
+                      source_loc,
+                      arena->New<IntrinsicExpression>(
+                          IntrinsicExpression::Intrinsic::Print),
+                      false)}));
   auto print = arena->New<FunctionDeclaration>(
       source_loc, "Print", std::vector<GenericBinding>(),
       arena->New<TuplePattern>(source_loc, print_params),

+ 12 - 24
executable_semantics/interpreter/interpreter.cpp

@@ -857,17 +857,20 @@ auto Interpreter::StepStmt() -> Transition {
       return UnwindTo{&cast<Continue>(stmt).loop()};
     }
     case Statement::Kind::Block: {
-      if (act->pos() == 0) {
-        const Block& block = cast<Block>(stmt);
-        if (block.sequence()) {
-          act->StartScope(Scope(CurrentEnv()));
-          return Spawn{arena_->New<StatementAction>(*block.sequence())};
-        } else {
-          return Done{};
-        }
-      } else {
+      const auto& block = cast<Block>(stmt);
+      if (act->pos() >= static_cast<int>(block.statements().size())) {
+        // If the position is past the end of the block, end processing. Note
+        // that empty blocks immediately end.
         return Done{};
       }
+      // Initialize a scope when starting a block.
+      if (act->pos() == 0) {
+        act->StartScope(Scope(CurrentEnv()));
+      }
+      // Process the next statement in the block. The position will be
+      // incremented as part of Spawn.
+      return Spawn{
+          arena_->New<StatementAction>(block.statements()[act->pos()])};
     }
     case Statement::Kind::VariableDefinition: {
       const auto& definition = cast<VariableDefinition>(stmt);
@@ -962,21 +965,6 @@ auto Interpreter::StepStmt() -> Transition {
         const FunctionDeclaration& function = cast<Return>(stmt).function();
         return UnwindPast{*function.body(), act->results()[0]};
       }
-    case Statement::Kind::Sequence: {
-      //    { { (s1,s2) :: C, E, F} :: S, H}
-      // -> { { s1 :: s2 :: C, E, F} :: S, H}
-      const auto& seq = cast<Sequence>(stmt);
-      if (act->pos() == 0) {
-        return Spawn{arena_->New<StatementAction>(&seq.statement())};
-      } else {
-        if (seq.next()) {
-          return Delegate{
-              arena_->New<StatementAction>(*cast<Sequence>(stmt).next())};
-        } else {
-          return Done{};
-        }
-      }
-    }
     case Statement::Kind::Continuation: {
       CHECK(act->pos() == 0);
       // Create a continuation object by creating a frame similar the

+ 2 - 10
executable_semantics/interpreter/resolve_control_flow.cpp

@@ -51,18 +51,10 @@ static void ResolveControlFlow(
       }
       return;
     }
-    case Statement::Kind::Sequence: {
-      auto& seq = cast<Sequence>(*statement);
-      ResolveControlFlow(&seq.statement(), function, loop);
-      if (seq.next().has_value()) {
-        ResolveControlFlow(*seq.next(), function, loop);
-      }
-      return;
-    }
     case Statement::Kind::Block: {
       auto& block = cast<Block>(*statement);
-      if (block.sequence().has_value()) {
-        ResolveControlFlow(*block.sequence(), function, loop);
+      for (auto* block_statement : block.statements()) {
+        ResolveControlFlow(block_statement, function, loop);
       }
       return;
     }

+ 15 - 28
executable_semantics/interpreter/type_checker.cpp

@@ -868,12 +868,12 @@ auto TypeChecker::TypeCheckStmt(Nonnull<Statement*> s, TypeEnv types,
       return TCResult(types);
     case Statement::Kind::Block: {
       auto& block = cast<Block>(*s);
-      if (block.sequence()) {
-        TypeCheckStmt(*block.sequence(), types, values, return_type_context);
-        return TCResult(types);
-      } else {
-        return TCResult(types);
+      for (auto* block_statement : block.statements()) {
+        auto result =
+            TypeCheckStmt(block_statement, types, values, return_type_context);
+        types = result.types;
       }
+      return TCResult(types);
     }
     case Statement::Kind::VariableDefinition: {
       auto& var = cast<VariableDefinition>(*s);
@@ -882,18 +882,6 @@ auto TypeChecker::TypeCheckStmt(Nonnull<Statement*> s, TypeEnv types,
       auto lhs_res = TypeCheckPattern(&var.pattern(), types, values, &rhs_ty);
       return TCResult(lhs_res.types);
     }
-    case Statement::Kind::Sequence: {
-      auto& seq = cast<Sequence>(*s);
-      auto stmt_res =
-          TypeCheckStmt(&seq.statement(), types, values, return_type_context);
-      auto checked_types = stmt_res.types;
-      if (seq.next()) {
-        auto next_res = TypeCheckStmt(*seq.next(), checked_types, values,
-                                      return_type_context);
-        checked_types = next_res.types;
-      }
-      return TCResult(checked_types);
-    }
     case Statement::Kind::Assign: {
       auto& assign = cast<Assign>(*s);
       TypeCheckExp(&assign.rhs(), types, values);
@@ -1003,9 +991,17 @@ void TypeChecker::ExpectReturnOnAllPaths(
       }
       return;
     }
-    case Statement::Kind::Block:
-      ExpectReturnOnAllPaths(cast<Block>(*stmt).sequence(), stmt->source_loc());
+    case Statement::Kind::Block: {
+      auto& block = cast<Block>(*stmt);
+      if (block.statements().empty()) {
+        FATAL_COMPILATION_ERROR(stmt->source_loc())
+            << "control-flow reaches end of function that provides a `->` "
+               "return type without reaching a return statement";
+      }
+      ExpectReturnOnAllPaths(block.statements()[block.statements().size() - 1],
+                             block.source_loc());
       return;
+    }
     case Statement::Kind::If: {
       auto& if_stmt = cast<If>(*stmt);
       ExpectReturnOnAllPaths(&if_stmt.then_block(), stmt->source_loc());
@@ -1014,15 +1010,6 @@ void TypeChecker::ExpectReturnOnAllPaths(
     }
     case Statement::Kind::Return:
       return;
-    case Statement::Kind::Sequence: {
-      auto& seq = cast<Sequence>(*stmt);
-      if (seq.next()) {
-        ExpectReturnOnAllPaths(seq.next(), stmt->source_loc());
-      } else {
-        ExpectReturnOnAllPaths(&seq.statement(), stmt->source_loc());
-      }
-      return;
-    }
     case Statement::Kind::Continuation:
     case Statement::Kind::Run:
     case Statement::Kind::Await:

+ 16 - 15
executable_semantics/syntax/parser.ypp

@@ -106,8 +106,7 @@
 %type <std::pair<Nonnull<Expression*>, bool>> return_expression
 %type <Nonnull<Block*>> nonempty_block
 %type <Nonnull<Block*>> block
-%type <Nonnull<Sequence*>> nonempty_statement_list
-%type <std::optional<Nonnull<Sequence*>>> statement_list
+%type <std::vector<Nonnull<Statement*>>> statement_list
 %type <Nonnull<Expression*>> expression
 %type <GenericBinding> generic_binding
 %type <std::vector<GenericBinding>> deduced_params
@@ -593,9 +592,8 @@ optional_else:
     { $$ = std::nullopt; }
 | ELSE if_statement
     {
-      $$ = arena->New<Block>(
-          context.source_loc(),
-          arena->New<Sequence>(context.source_loc(), $2, std::nullopt));
+      $$ = arena->New<Block>(context.source_loc(),
+                             std::vector<Nonnull<Statement*>>({$2}));
     }
 | ELSE block
     { $$ = $2; }
@@ -608,21 +606,24 @@ return_expression:
 ;
 statement_list:
   // Empty
-    { $$ = std::nullopt; }
-| nonempty_statement_list
-    { $$ = $1; }
-;
-nonempty_statement_list:
-  statement statement_list
-    { $$ = arena->New<Sequence>(context.source_loc(), $1, $2); }
+    { $$ = {}; }
+| statement_list statement
+    {
+      $$ = std::move($1);
+      $$.push_back($2);
+    }
 ;
 block:
   LEFT_CURLY_BRACE statement_list RIGHT_CURLY_BRACE
-    { $$ = arena->New<Block>(context.source_loc(), $2); }
+    { $$ = arena->New<Block>(context.source_loc(), std::move($2)); }
 ;
 nonempty_block:
-  LEFT_CURLY_BRACE nonempty_statement_list RIGHT_CURLY_BRACE
-    { $$ = arena->New<Block>(context.source_loc(), $2); }
+  LEFT_CURLY_BRACE statement_list statement RIGHT_CURLY_BRACE
+    {
+      $2.push_back($3);
+      $$ = arena->New<Block>(context.source_loc(), std::move($2));
+    }
+;
 return_type:
   // Empty
     { $$ = {arena->New<TupleLiteral>(context.source_loc()), true}; }