Collapse Sequence into Block. (#927)

This commit is contained in:
Jon Meow
2021-11-01 14:59:39 -07:00
committed by GitHub
parent e69ec3f528
commit 904774fbb8
7 changed files with 60 additions and 131 deletions
+2 -15
View File
@@ -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
View File
@@ -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:
+16 -15
View File
@@ -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}; }