mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
Change Alternative to a class (#853)
Revives BisonWrap because this seems a reasonable use of it (avoiding the need to have an std::optional or pointer for Alternative, both of which I thought could be unclear about the intent).
This commit is contained in:
@@ -30,8 +30,8 @@ void Declaration::Print(llvm::raw_ostream& out) const {
|
||||
case Kind::ChoiceDeclaration: {
|
||||
const auto& choice = cast<ChoiceDeclaration>(*this);
|
||||
out << "choice " << choice.Name() << " {\n";
|
||||
for (const auto& [name, signature] : choice.Alternatives()) {
|
||||
out << "alt " << name << " " << *signature << ";\n";
|
||||
for (const auto& alt : choice.Alternatives()) {
|
||||
out << "alt " << alt.name() << " " << alt.signature() << ";\n";
|
||||
}
|
||||
out << "}\n";
|
||||
break;
|
||||
|
||||
@@ -95,10 +95,21 @@ class ClassDeclaration : public Declaration {
|
||||
|
||||
class ChoiceDeclaration : public Declaration {
|
||||
public:
|
||||
ChoiceDeclaration(
|
||||
SourceLocation loc, std::string name,
|
||||
std::vector<std::pair<std::string, Nonnull<const Expression*>>>
|
||||
alternatives)
|
||||
class Alternative {
|
||||
public:
|
||||
Alternative(std::string name, Nonnull<const Expression*> signature)
|
||||
: name_(name), signature_(signature) {}
|
||||
|
||||
auto name() const -> const std::string& { return name_; }
|
||||
auto signature() const -> const Expression& { return *signature_; }
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
Nonnull<const Expression*> signature_;
|
||||
};
|
||||
|
||||
ChoiceDeclaration(SourceLocation loc, std::string name,
|
||||
std::vector<Alternative> alternatives)
|
||||
: Declaration(Kind::ChoiceDeclaration, loc),
|
||||
name(std::move(name)),
|
||||
alternatives(std::move(alternatives)) {}
|
||||
@@ -108,14 +119,13 @@ class ChoiceDeclaration : public Declaration {
|
||||
}
|
||||
|
||||
auto Name() const -> const std::string& { return name; }
|
||||
auto Alternatives() const -> const
|
||||
std::vector<std::pair<std::string, Nonnull<const Expression*>>>& {
|
||||
auto Alternatives() const -> const std::vector<Alternative>& {
|
||||
return alternatives;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string name;
|
||||
std::vector<std::pair<std::string, Nonnull<const Expression*>>> alternatives;
|
||||
std::vector<Alternative> alternatives;
|
||||
};
|
||||
|
||||
// Global variable definition implements the Declaration concept.
|
||||
|
||||
@@ -151,9 +151,9 @@ void Interpreter::InitEnv(const Declaration& d, Env* env) {
|
||||
case Declaration::Kind::ChoiceDeclaration: {
|
||||
const auto& choice = cast<ChoiceDeclaration>(d);
|
||||
VarValues alts;
|
||||
for (const auto& [name, signature] : choice.Alternatives()) {
|
||||
auto t = InterpExp(Env(arena), signature);
|
||||
alts.push_back(make_pair(name, t));
|
||||
for (const auto& alternative : choice.Alternatives()) {
|
||||
auto t = InterpExp(Env(arena), &alternative.signature());
|
||||
alts.push_back(make_pair(alternative.name(), t));
|
||||
}
|
||||
auto ct = arena->New<ChoiceType>(choice.Name(), std::move(alts));
|
||||
auto a = heap.AllocateValue(ct);
|
||||
|
||||
@@ -1043,9 +1043,9 @@ void TypeChecker::TopLevel(const Declaration& d, TypeCheckContext* tops) {
|
||||
case Declaration::Kind::ChoiceDeclaration: {
|
||||
const auto& choice = cast<ChoiceDeclaration>(d);
|
||||
VarValues alts;
|
||||
for (const auto& [name, signature] : choice.Alternatives()) {
|
||||
auto t = interpreter.InterpExp(tops->values, signature);
|
||||
alts.push_back(std::make_pair(name, t));
|
||||
for (const auto& alternative : choice.Alternatives()) {
|
||||
auto t = interpreter.InterpExp(tops->values, &alternative.signature());
|
||||
alts.push_back(std::make_pair(alternative.name(), t));
|
||||
}
|
||||
auto ct = arena->New<ChoiceType>(choice.Name(), std::move(alts));
|
||||
Address a = interpreter.AllocateValue(ct);
|
||||
|
||||
@@ -6,6 +6,12 @@ load("@mypy_integration//:mypy.bzl", "mypy_test")
|
||||
|
||||
package(default_visibility = ["//executable_semantics:__pkg__"])
|
||||
|
||||
cc_library(
|
||||
name = "bison_wrap",
|
||||
hdrs = ["bison_wrap.h"],
|
||||
deps = ["//common:check"],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "syntax",
|
||||
srcs = [
|
||||
@@ -27,6 +33,7 @@ cc_library(
|
||||
"-Wno-writable-strings",
|
||||
],
|
||||
deps = [
|
||||
":bison_wrap",
|
||||
"//common:check",
|
||||
"//common:ostream",
|
||||
"//common:string_helpers",
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
#ifndef EXECUTABLE_SEMANTICS_SYNTAX_BISON_WRAP_H_
|
||||
#define EXECUTABLE_SEMANTICS_SYNTAX_BISON_WRAP_H_
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "common/check.h"
|
||||
|
||||
namespace Carbon {
|
||||
|
||||
// Bison requires that types be default initializable for use with its variant
|
||||
// semantics. This wraps arbitrary types to support a default constructor, while
|
||||
// still requiring they be properly initialized.
|
||||
template <typename T>
|
||||
class BisonWrap {
|
||||
public:
|
||||
// Assigning a value initializes the wrapper.
|
||||
auto operator=(T&& rhs) -> BisonWrap& {
|
||||
val = std::move(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Support transparent conversion to the wrapped type.
|
||||
operator T() { return Release(); }
|
||||
|
||||
// Deliberately releases the contained value. Errors if not initialized.
|
||||
// Called directly in parser.ypp when releasing pairs.
|
||||
auto Release() -> T {
|
||||
CHECK(val.has_value());
|
||||
T ret = std::move(*val);
|
||||
val.reset();
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
std::optional<T> val;
|
||||
};
|
||||
|
||||
} // namespace Carbon
|
||||
|
||||
#endif // EXECUTABLE_SEMANTICS_SYNTAX_BISON_WRAP_H_
|
||||
@@ -73,6 +73,7 @@
|
||||
#include "executable_semantics/ast/pattern.h"
|
||||
#include "executable_semantics/common/arena.h"
|
||||
#include "executable_semantics/common/nonnull.h"
|
||||
#include "executable_semantics/syntax/bison_wrap.h"
|
||||
|
||||
namespace Carbon {
|
||||
class ParseAndLexContext;
|
||||
@@ -129,9 +130,9 @@
|
||||
%type <ParenContents<Pattern>> paren_pattern_base
|
||||
%type <ParenContents<Pattern>::Element> paren_pattern_element
|
||||
%type <ParenContents<Pattern>> paren_pattern_contents
|
||||
%type <std::pair<std::string, Nonnull<const Expression*>>> alternative
|
||||
%type <std::vector<std::pair<std::string, Nonnull<const Expression*>>>> alternative_list
|
||||
%type <std::vector<std::pair<std::string, Nonnull<const Expression*>>>> alternative_list_contents
|
||||
%type <BisonWrap<ChoiceDeclaration::Alternative>> alternative
|
||||
%type <std::vector<ChoiceDeclaration::Alternative>> alternative_list
|
||||
%type <std::vector<ChoiceDeclaration::Alternative>> alternative_list_contents
|
||||
%type <std::pair<Nonnull<const Pattern*>, Nonnull<const Statement*>>> clause
|
||||
%type <std::vector<std::pair<Nonnull<const Pattern*>, Nonnull<const Statement*>>>> clause_list
|
||||
|
||||
@@ -658,10 +659,10 @@ member_list:
|
||||
;
|
||||
alternative:
|
||||
identifier tuple
|
||||
{ $$ = std::pair<std::string, Nonnull<const Expression*>>($1, $2); }
|
||||
{ $$ = ChoiceDeclaration::Alternative($1, $2); }
|
||||
| identifier
|
||||
{
|
||||
$$ = std::pair<std::string, Nonnull<const Expression*>>(
|
||||
$$ = ChoiceDeclaration::Alternative(
|
||||
$1, arena->New<TupleLiteral>(context.SourceLoc()));
|
||||
}
|
||||
;
|
||||
@@ -675,11 +676,11 @@ alternative_list:
|
||||
;
|
||||
alternative_list_contents:
|
||||
alternative
|
||||
{ $$ = {$1}; }
|
||||
{ $$ = {std::move($1)}; }
|
||||
| alternative_list_contents COMMA alternative
|
||||
{
|
||||
$$ = $1;
|
||||
$$.push_back($3);
|
||||
$$.push_back(std::move($3));
|
||||
}
|
||||
;
|
||||
declaration:
|
||||
|
||||
Reference in New Issue
Block a user