Be more explicit about AST types (#921)

This was born out of wanting FunctionDeclaration to explicitly have a Block for a body, and became a bit more of specifying types around. Note this forces exec_program to generate a Block for print()'s body, which is probably more correct as now we can expect a standard FunctionDeclaration AST structure, even for the built-ins.

There is a syntactic change here: a continuation's body is now a Block, not just a Statement. I've added an example disallowed test case. I think this is more reasonable syntax.

Other than that, note that optional_else now generates a valid Block. This has me thinking about whether we can eliminate Sequence, but that seemed well out of scope for this.
This commit is contained in:
Jon Meow
2021-10-28 13:54:45 -07:00
committed by GitHub
parent dea277d8e1
commit bbd4940e6d
11 changed files with 143 additions and 122 deletions
@@ -22,10 +22,15 @@ static void AddIntrinsics(Nonnull<Arena*> arena,
source_loc, "format_str",
arena->New<ExpressionPattern>(
arena->New<StringTypeLiteral>(source_loc)))};
auto print_return = arena->New<Return>(
auto print_return = arena->New<Block>(
source_loc,
arena->New<IntrinsicExpression>(IntrinsicExpression::Intrinsic::Print),
false);
arena->New<Sequence>(
source_loc,
arena->New<Return>(source_loc,
arena->New<IntrinsicExpression>(
IntrinsicExpression::Intrinsic::Print),
false),
std::nullopt));
auto print = arena->New<FunctionDeclaration>(
source_loc, "Print", std::vector<GenericBinding>(),
arena->New<TuplePattern>(source_loc, print_params),
@@ -859,9 +859,9 @@ auto Interpreter::StepStmt() -> Transition {
case Statement::Kind::Block: {
if (act->pos() == 0) {
const Block& block = cast<Block>(stmt);
if (block.statement()) {
if (block.sequence()) {
act->StartScope(Scope(CurrentEnv()));
return Spawn{arena_->New<StatementAction>(*block.statement())};
return Spawn{arena_->New<StatementAction>(*block.sequence())};
} else {
return Done{};
}
@@ -937,13 +937,13 @@ auto Interpreter::StepStmt() -> Transition {
// S, H}
// -> { { then_stmt :: C, E, F } :: S, H}
return Delegate{
arena_->New<StatementAction>(&cast<If>(stmt).then_statement())};
} else if (cast<If>(stmt).else_statement()) {
arena_->New<StatementAction>(&cast<If>(stmt).then_block())};
} else if (cast<If>(stmt).else_block()) {
// { {false :: if ([]) then_stmt else else_stmt :: C, E, F} ::
// S, H}
// -> { { else_stmt :: C, E, F } :: S, H}
return Delegate{
arena_->New<StatementAction>(*cast<If>(stmt).else_statement())};
arena_->New<StatementAction>(*cast<If>(stmt).else_block())};
} else {
return Done{};
}
@@ -45,9 +45,9 @@ static void ResolveControlFlow(
return;
case Statement::Kind::If: {
auto& if_stmt = cast<If>(*statement);
ResolveControlFlow(&if_stmt.then_statement(), function, loop);
if (if_stmt.else_statement().has_value()) {
ResolveControlFlow(*if_stmt.else_statement(), function, loop);
ResolveControlFlow(&if_stmt.then_block(), function, loop);
if (if_stmt.else_block().has_value()) {
ResolveControlFlow(*if_stmt.else_block(), function, loop);
}
return;
}
@@ -61,8 +61,8 @@ static void ResolveControlFlow(
}
case Statement::Kind::Block: {
auto& block = cast<Block>(*statement);
if (block.statement().has_value()) {
ResolveControlFlow(*block.statement(), function, loop);
if (block.sequence().has_value()) {
ResolveControlFlow(*block.sequence(), function, loop);
}
return;
}
@@ -868,8 +868,8 @@ auto TypeChecker::TypeCheckStmt(Nonnull<Statement*> s, TypeEnv types,
return TCResult(types);
case Statement::Kind::Block: {
auto& block = cast<Block>(*s);
if (block.statement()) {
TypeCheckStmt(*block.statement(), types, values, return_type_context);
if (block.sequence()) {
TypeCheckStmt(*block.sequence(), types, values, return_type_context);
return TCResult(types);
} else {
return TCResult(types);
@@ -911,10 +911,9 @@ auto TypeChecker::TypeCheckStmt(Nonnull<Statement*> s, TypeEnv types,
TypeCheckExp(&if_stmt.condition(), types, values);
ExpectType(s->source_loc(), "condition of `if`", arena_->New<BoolType>(),
&if_stmt.condition().static_type());
TypeCheckStmt(&if_stmt.then_statement(), types, values,
return_type_context);
if (if_stmt.else_statement()) {
TypeCheckStmt(*if_stmt.else_statement(), types, values,
TypeCheckStmt(&if_stmt.then_block(), types, values, return_type_context);
if (if_stmt.else_block()) {
TypeCheckStmt(*if_stmt.else_block(), types, values,
return_type_context);
}
return TCResult(types);
@@ -1005,13 +1004,12 @@ void TypeChecker::ExpectReturnOnAllPaths(
return;
}
case Statement::Kind::Block:
ExpectReturnOnAllPaths(cast<Block>(*stmt).statement(),
stmt->source_loc());
ExpectReturnOnAllPaths(cast<Block>(*stmt).sequence(), stmt->source_loc());
return;
case Statement::Kind::If: {
auto& if_stmt = cast<If>(*stmt);
ExpectReturnOnAllPaths(&if_stmt.then_statement(), stmt->source_loc());
ExpectReturnOnAllPaths(if_stmt.else_statement(), stmt->source_loc());
ExpectReturnOnAllPaths(&if_stmt.then_block(), stmt->source_loc());
ExpectReturnOnAllPaths(if_stmt.else_block(), stmt->source_loc());
return;
}
case Statement::Kind::Return: