mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-30 22:02:41 +01:00
Sorry about the big change, this is hard to split. ParenContents is used by both, templated, and expects the same pointer type. While I could duplicate ParenContents with some ExpressionParenContents or PatternParenContents, that seems a little kludgy versus a single large change handling both. The worst of it is that Expression is already pretty sweeping, Pattern is really just incrementally adding. That said, I believe this includes a couple fixes I found with incorrect use of dyn_cast in typecheck.cpp (checked nullptr at the wrong step in 2 code locations). There's also a missing `*` in member.cpp this caught. I adjust passing of expressions for Return due to nullness (I felt adding another constructor was the best solution). I add a `.Release()` to BisonWrap due to things like `$3.first` needing some way to work through BIsonWrap. I felt this was better than `operator->`, but feel free to comment if you prefer the other path (`.Release()` conveniently lets me do pair unwrapping, so it felt a better solution). I do add a TODO to think about better Ptr-to-Ptr cast<> support too, though, as that doesn't work cleanly with LLVM's infra. But so far it seems to only come up in one spot, so I'm not prioritizing it.
88 lines
2.8 KiB
C++
88 lines
2.8 KiB
C++
// 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_AST_PAREN_CONTENTS_H_
|
|
#define EXECUTABLE_SEMANTICS_AST_PAREN_CONTENTS_H_
|
|
|
|
#include <optional>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "executable_semantics/ast/source_location.h"
|
|
#include "executable_semantics/common/error.h"
|
|
|
|
namespace Carbon {
|
|
|
|
// Represents the syntactic contents of an expression or pattern delimited by
|
|
// parentheses. In those syntaxes, parentheses can be used either for grouping
|
|
// or for forming a tuple, depending on their context and the syntax of their
|
|
// contents; this class helps calling code resolve that ambiguity. Since that
|
|
// ambiguity is purely syntactic, this class should only be needed during
|
|
// parsing.
|
|
//
|
|
// `Term` is the type of the syntactic grouping being built, and the type of
|
|
// the individual syntactic units it's built from; typically it should be
|
|
// either `Expression` or `Pattern`.
|
|
template <typename Term>
|
|
struct ParenContents {
|
|
struct Element {
|
|
std::optional<std::string> name;
|
|
Ptr<const Term> term;
|
|
};
|
|
|
|
// If this object represents a single term, with no name and no trailing
|
|
// comma, this method returns that term. This typically means the parentheses
|
|
// can be interpreted as grouping.
|
|
auto SingleTerm() const -> std::optional<Ptr<const Term>>;
|
|
|
|
// Converts `elements` to std::vector<TupleElement>. TupleElement must
|
|
// have a constructor that takes a std::string and a Ptr<const Term>.
|
|
//
|
|
// TODO: Find a way to deduce TupleElement from Term.
|
|
template <typename TupleElement>
|
|
auto TupleElements(SourceLocation loc) const -> std::vector<TupleElement>;
|
|
|
|
std::vector<Element> elements;
|
|
bool has_trailing_comma;
|
|
};
|
|
|
|
// Implementation details only below here.
|
|
|
|
template <typename Term>
|
|
auto ParenContents<Term>::SingleTerm() const -> std::optional<Ptr<const Term>> {
|
|
if (elements.size() == 1 && !elements.front().name.has_value() &&
|
|
!has_trailing_comma) {
|
|
return elements.front().term;
|
|
} else {
|
|
return std::nullopt;
|
|
}
|
|
}
|
|
|
|
template <typename Term>
|
|
template <typename TupleElement>
|
|
auto ParenContents<Term>::TupleElements(SourceLocation loc) const
|
|
-> std::vector<TupleElement> {
|
|
std::vector<TupleElement> result;
|
|
int i = 0;
|
|
bool seen_named_member = false;
|
|
for (auto element : elements) {
|
|
if (element.name.has_value()) {
|
|
seen_named_member = true;
|
|
result.push_back(TupleElement(*element.name, element.term));
|
|
} else {
|
|
if (seen_named_member) {
|
|
FATAL_PROGRAM_ERROR(loc)
|
|
<< "positional members must come before named members";
|
|
}
|
|
result.push_back(TupleElement(std::to_string(i), element.term));
|
|
}
|
|
++i;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
} // namespace Carbon
|
|
|
|
#endif // EXECUTABLE_SEMANTICS_AST_PAREN_CONTENTS_H_
|