mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-06 07:54:41 +01:00
Change Match clauses from pairs to classes (#858)
Updates style of the Match class at the same time.
This commit is contained in:
@@ -20,12 +20,12 @@ void Statement::PrintDepth(int depth, llvm::raw_ostream& out) const {
|
||||
switch (Tag()) {
|
||||
case Kind::Match: {
|
||||
const auto& match = cast<Match>(*this);
|
||||
out << "match (" << *match.Exp() << ") {";
|
||||
out << "match (" << match.expression() << ") {";
|
||||
if (depth < 0 || depth > 1) {
|
||||
out << "\n";
|
||||
for (auto& clause : match.Clauses()) {
|
||||
out << "case " << *clause.first << " =>\n";
|
||||
clause.second->PrintDepth(depth - 1, out);
|
||||
for (auto& clause : match.clauses()) {
|
||||
out << "case " << clause.pattern() << " =>\n";
|
||||
clause.statement().PrintDepth(depth - 1, out);
|
||||
out << "\n";
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -238,24 +238,39 @@ class Continue : public Statement {
|
||||
|
||||
class Match : public Statement {
|
||||
public:
|
||||
Match(SourceLocation loc, Nonnull<Expression*> exp,
|
||||
std::vector<std::pair<Nonnull<Pattern*>, Nonnull<Statement*>>> clauses)
|
||||
: Statement(Kind::Match, loc), exp(exp), clauses(std::move(clauses)) {}
|
||||
class Clause {
|
||||
public:
|
||||
Clause(Nonnull<Pattern*> pattern, Nonnull<Statement*> statement)
|
||||
: pattern_(pattern), statement_(statement) {}
|
||||
|
||||
auto pattern() const -> const Pattern& { return *pattern_; }
|
||||
auto pattern() -> Pattern& { return *pattern_; }
|
||||
auto statement() const -> const Statement& { return *statement_; }
|
||||
auto statement() -> Statement& { return *statement_; }
|
||||
|
||||
private:
|
||||
Nonnull<Pattern*> pattern_;
|
||||
Nonnull<Statement*> statement_;
|
||||
};
|
||||
|
||||
Match(SourceLocation loc, Nonnull<Expression*> expression,
|
||||
std::vector<Clause> clauses)
|
||||
: Statement(Kind::Match, loc),
|
||||
expression_(expression),
|
||||
clauses_(std::move(clauses)) {}
|
||||
|
||||
static auto classof(const Statement* stmt) -> bool {
|
||||
return stmt->Tag() == Kind::Match;
|
||||
}
|
||||
|
||||
auto Exp() const -> Nonnull<const Expression*> { return exp; }
|
||||
auto Exp() -> Nonnull<Expression*> { return exp; }
|
||||
auto Clauses() const
|
||||
-> llvm::ArrayRef<std::pair<Nonnull<Pattern*>, Nonnull<Statement*>>> {
|
||||
return clauses;
|
||||
}
|
||||
auto expression() const -> const Expression& { return *expression_; }
|
||||
auto expression() -> Expression& { return *expression_; }
|
||||
auto clauses() const -> llvm::ArrayRef<Clause> { return clauses_; }
|
||||
auto clauses() -> llvm::MutableArrayRef<Clause> { return clauses_; }
|
||||
|
||||
private:
|
||||
Nonnull<Expression*> exp;
|
||||
std::vector<std::pair<Nonnull<Pattern*>, Nonnull<Statement*>>> clauses;
|
||||
Nonnull<Expression*> expression_;
|
||||
std::vector<Clause> clauses_;
|
||||
};
|
||||
|
||||
// A continuation statement.
|
||||
|
||||
@@ -737,7 +737,7 @@ auto Interpreter::StepStmt() -> Transition {
|
||||
// { { (match (e) ...) :: C, E, F} :: S, H}
|
||||
// -> { { e :: (match ([]) ...) :: C, E, F} :: S, H}
|
||||
frame->scopes.Push(arena->New<Scope>(CurrentEnv()));
|
||||
return Spawn{arena->New<ExpressionAction>(match_stmt.Exp())};
|
||||
return Spawn{arena->New<ExpressionAction>(&match_stmt.expression())};
|
||||
} else {
|
||||
// Regarding act->Pos():
|
||||
// * odd: start interpreting the pattern of a clause
|
||||
@@ -749,31 +749,31 @@ auto Interpreter::StepStmt() -> Transition {
|
||||
// * 2: the pattern for clause 1
|
||||
// * ...
|
||||
auto clause_num = (act->Pos() - 1) / 2;
|
||||
if (clause_num >= static_cast<int>(match_stmt.Clauses().size())) {
|
||||
if (clause_num >= static_cast<int>(match_stmt.clauses().size())) {
|
||||
DeallocateScope(frame->scopes.Top());
|
||||
frame->scopes.Pop();
|
||||
return Done{};
|
||||
}
|
||||
auto c = match_stmt.Clauses()[clause_num];
|
||||
auto c = match_stmt.clauses()[clause_num];
|
||||
|
||||
if (act->Pos() % 2 == 1) {
|
||||
// start interpreting the pattern of the clause
|
||||
// { {v :: (match ([]) ...) :: C, E, F} :: S, H}
|
||||
// -> { {pi :: (match ([]) ...) :: C, E, F} :: S, H}
|
||||
return Spawn{arena->New<PatternAction>(c.first)};
|
||||
return Spawn{arena->New<PatternAction>(&c.pattern())};
|
||||
} else { // try to match
|
||||
auto v = act->Results()[0];
|
||||
auto pat = act->Results()[clause_num + 1];
|
||||
std::optional<Env> matches = PatternMatch(pat, v, stmt->SourceLoc());
|
||||
if (matches) { // we have a match, start the body
|
||||
// Ensure we don't process any more clauses.
|
||||
act->SetPos(2 * match_stmt.Clauses().size() + 1);
|
||||
act->SetPos(2 * match_stmt.clauses().size() + 1);
|
||||
|
||||
for (const auto& [name, value] : *matches) {
|
||||
frame->scopes.Top()->values.Set(name, value);
|
||||
frame->scopes.Top()->locals.push_back(name);
|
||||
}
|
||||
return Spawn{arena->New<StatementAction>(c.second)};
|
||||
return Spawn{arena->New<StatementAction>(&c.statement())};
|
||||
} else {
|
||||
return RunAgain{};
|
||||
}
|
||||
|
||||
@@ -631,10 +631,10 @@ auto TypeChecker::TypeCheckCase(Nonnull<const Value*> expected,
|
||||
Nonnull<Pattern*> pat, Nonnull<Statement*> body,
|
||||
TypeEnv types, Env values,
|
||||
Nonnull<ReturnTypeContext*> return_type_context)
|
||||
-> std::pair<Nonnull<Pattern*>, Nonnull<Statement*>> {
|
||||
-> Match::Clause {
|
||||
auto pat_res = TypeCheckPattern(pat, types, values, expected);
|
||||
auto res = TypeCheckStmt(body, pat_res.types, values, return_type_context);
|
||||
return std::make_pair(pat, res.stmt);
|
||||
return Match::Clause(pat, res.stmt);
|
||||
}
|
||||
|
||||
auto TypeChecker::TypeCheckStmt(Nonnull<Statement*> s, TypeEnv types,
|
||||
@@ -644,13 +644,12 @@ auto TypeChecker::TypeCheckStmt(Nonnull<Statement*> s, TypeEnv types,
|
||||
switch (s->Tag()) {
|
||||
case Statement::Kind::Match: {
|
||||
auto& match = cast<Match>(*s);
|
||||
auto res = TypeCheckExp(match.Exp(), types, values);
|
||||
auto res = TypeCheckExp(&match.expression(), types, values);
|
||||
auto res_type = res.type;
|
||||
std::vector<std::pair<Nonnull<Pattern*>, Nonnull<Statement*>>>
|
||||
new_clauses;
|
||||
for (auto& clause : match.Clauses()) {
|
||||
new_clauses.push_back(TypeCheckCase(res_type, clause.first,
|
||||
clause.second, types, values,
|
||||
std::vector<Match::Clause> new_clauses;
|
||||
for (auto& clause : match.clauses()) {
|
||||
new_clauses.push_back(TypeCheckCase(res_type, &clause.pattern(),
|
||||
&clause.statement(), types, values,
|
||||
return_type_context));
|
||||
}
|
||||
auto new_s = arena->New<Match>(s->SourceLoc(), res.exp, new_clauses);
|
||||
@@ -806,14 +805,14 @@ auto TypeChecker::CheckOrEnsureReturn(
|
||||
switch (stmt->Tag()) {
|
||||
case Statement::Kind::Match: {
|
||||
auto& match = cast<Match>(*stmt);
|
||||
std::vector<std::pair<Nonnull<Pattern*>, Nonnull<Statement*>>>
|
||||
new_clauses;
|
||||
for (const auto& clause : match.Clauses()) {
|
||||
auto s = CheckOrEnsureReturn(clause.second, omitted_ret_type,
|
||||
std::vector<Match::Clause> new_clauses;
|
||||
for (auto& clause : match.clauses()) {
|
||||
auto s = CheckOrEnsureReturn(&clause.statement(), omitted_ret_type,
|
||||
stmt->SourceLoc());
|
||||
new_clauses.push_back(std::make_pair(clause.first, s));
|
||||
new_clauses.push_back(Match::Clause(&clause.pattern(), s));
|
||||
}
|
||||
return arena->New<Match>(stmt->SourceLoc(), match.Exp(), new_clauses);
|
||||
return arena->New<Match>(stmt->SourceLoc(), &match.expression(),
|
||||
new_clauses);
|
||||
}
|
||||
case Statement::Kind::Block:
|
||||
return arena->New<Block>(
|
||||
|
||||
@@ -130,7 +130,7 @@ class TypeChecker {
|
||||
auto TypeCheckCase(Nonnull<const Value*> expected, Nonnull<Pattern*> pat,
|
||||
Nonnull<Statement*> body, TypeEnv types, Env values,
|
||||
Nonnull<ReturnTypeContext*> return_type_context)
|
||||
-> std::pair<Nonnull<Pattern*>, Nonnull<Statement*>>;
|
||||
-> Match::Clause;
|
||||
|
||||
auto TypeOfFunDef(TypeEnv types, Env values, FunctionDefinition* fun_def)
|
||||
-> Nonnull<const Value*>;
|
||||
|
||||
@@ -133,8 +133,8 @@
|
||||
%type <BisonWrap<ChoiceDeclaration::Alternative>> alternative
|
||||
%type <std::vector<ChoiceDeclaration::Alternative>> alternative_list
|
||||
%type <std::vector<ChoiceDeclaration::Alternative>> alternative_list_contents
|
||||
%type <std::pair<Nonnull<Pattern*>, Nonnull<Statement*>>> clause
|
||||
%type <std::vector<std::pair<Nonnull<Pattern*>, Nonnull<Statement*>>>> clause_list
|
||||
%type <BisonWrap<Match::Clause>> clause
|
||||
%type <std::vector<Match::Clause>> clause_list
|
||||
|
||||
%token
|
||||
// Most tokens have their spelling defined in lexer.lpp.
|
||||
@@ -501,13 +501,13 @@ maybe_empty_tuple_pattern:
|
||||
;
|
||||
clause:
|
||||
CASE pattern DOUBLE_ARROW statement
|
||||
{ $$ = std::pair<Nonnull<Pattern*>, Nonnull<Statement*>>($2, $4); }
|
||||
{ $$ = Match::Clause($2, $4); }
|
||||
| DEFAULT DOUBLE_ARROW statement
|
||||
{
|
||||
auto vp = arena -> New<BindingPattern>(
|
||||
context.SourceLoc(), std::nullopt,
|
||||
arena->New<AutoPattern>(context.SourceLoc()));
|
||||
$$ = std::pair<Nonnull<Pattern*>, Nonnull<Statement*>>(vp, $3);
|
||||
$$ = Match::Clause(arena->New<BindingPattern>(
|
||||
context.SourceLoc(), std::nullopt,
|
||||
arena->New<AutoPattern>(context.SourceLoc())),
|
||||
$3);
|
||||
}
|
||||
;
|
||||
clause_list:
|
||||
|
||||
Reference in New Issue
Block a user