mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
Collapse Sequence into Block. (#927)
This commit is contained in:
@@ -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";
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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}; }
|
||||
|
||||
Reference in New Issue
Block a user