Files
carbon-lang/executable_semantics/ast/paren_contents.h
T
Jon Meow 04ab30f231 Make the AST mutable (#849)
The code is pretty intertwined: having the AST be truly mutable means (to me) changing parser.ypp to return non-const values, but then the way things are passed around between objects should be non-const (particularly an issue with lists), which then creates issues with construction of lists in the TypeChecker, which then TypeChecker needs to mostly be non-const.

Due to the difficulties in breaking this apart, whereas I'd previously considering refactoring accessor naming in the same PR, I've largely avoided doing so. The intent is then that this PR focuses mainly on const -> non-const AST behavior.

call_main moves out of interpreter.cpp so that interpreter.cpp can receive a fully const AST.
2021-09-27 10:57:31 -07:00

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;
Nonnull<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<Nonnull<Term*>>;
// Converts `elements` to std::vector<TupleElement>. TupleElement must
// have a constructor that takes a std::string and a Nonnull<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<Nonnull<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_