Handle identifier value category properly. (#986)

This commit is contained in:
Geoff Romer
2021-12-15 13:27:36 -08:00
committed by GitHub
parent daf8729a75
commit c89ce1d570
9 changed files with 99 additions and 48 deletions
+10
View File
@@ -80,6 +80,7 @@ cc_library(
":source_location",
":statement",
":static_scope",
":value_category",
"//common:ostream",
"//executable_semantics/common:nonnull",
"@llvm-project//llvm:Support",
@@ -94,6 +95,7 @@ cc_library(
":ast_node",
":paren_contents",
":static_scope",
":value_category",
"//common:indirect_value",
"//common:ostream",
"//executable_semantics/common:arena",
@@ -146,6 +148,7 @@ cc_library(
":expression",
":source_location",
":static_scope",
":value_category",
"//common:ostream",
"//executable_semantics/common:arena",
"//executable_semantics/common:error",
@@ -171,6 +174,7 @@ cc_library(
deps = [
":ast_node",
":source_location",
":value_category",
"//executable_semantics/common:arena",
"//executable_semantics/common:error",
],
@@ -194,9 +198,15 @@ cc_library(
":expression",
":pattern",
":source_location",
":value_category",
"//common:check",
"//common:ostream",
"//executable_semantics/common:arena",
"@llvm-project//llvm:Support",
],
)
cc_library(
name = "value_category",
hdrs = ["value_category.h"],
)
+9
View File
@@ -15,6 +15,7 @@
#include "executable_semantics/ast/source_location.h"
#include "executable_semantics/ast/statement.h"
#include "executable_semantics/ast/static_scope.h"
#include "executable_semantics/ast/value_category.h"
#include "executable_semantics/common/nonnull.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/Compiler.h"
@@ -106,6 +107,8 @@ class GenericBinding : public AstNode {
// and after typechecking it's guaranteed to be true.
auto has_static_type() const -> bool { return static_type_.has_value(); }
auto value_category() const -> ValueCategory { return ValueCategory::Let; }
private:
std::string name_;
Nonnull<Expression*> type_;
@@ -228,6 +231,8 @@ class FunctionDeclaration : public Declaration {
auto body() const -> std::optional<Nonnull<const Block*>> { return body_; }
auto body() -> std::optional<Nonnull<Block*>> { return body_; }
auto value_category() const -> ValueCategory { return ValueCategory::Let; }
private:
std::string name_;
std::vector<Nonnull<GenericBinding*>> deduced_parameters_;
@@ -253,6 +258,8 @@ class ClassDeclaration : public Declaration {
auto name() const -> const std::string& { return name_; }
auto members() const -> llvm::ArrayRef<Nonnull<Member*>> { return members_; }
auto value_category() const -> ValueCategory { return ValueCategory::Let; }
private:
std::string name_;
std::vector<Nonnull<Member*>> members_;
@@ -304,6 +311,8 @@ class ChoiceDeclaration : public Declaration {
return alternatives_;
}
auto value_category() const -> ValueCategory { return ValueCategory::Let; }
private:
std::string name_;
std::vector<Nonnull<AlternativeSignature*>> alternatives_;
+1 -10
View File
@@ -15,6 +15,7 @@
#include "executable_semantics/ast/paren_contents.h"
#include "executable_semantics/ast/source_location.h"
#include "executable_semantics/ast/static_scope.h"
#include "executable_semantics/ast/value_category.h"
#include "executable_semantics/common/arena.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/Compiler.h"
@@ -25,16 +26,6 @@ class Value;
class Expression : public AstNode {
public:
// The value category of a Carbon expression indicates whether it evaluates
// to a variable or a value. A variable can be mutated, and can have its
// address taken, whereas a value cannot.
enum class ValueCategory {
// A variable. This roughly corresponds to a C/C++ lvalue.
Var,
// A value. This roughly corresponds to a C/C++ rvalue.
Let,
};
~Expression() override = 0;
void Print(llvm::raw_ostream& out) const override;
+2
View File
@@ -118,6 +118,8 @@ class BindingPattern : public Pattern {
auto type() const -> const Pattern& { return *type_; }
auto type() -> Pattern& { return *type_; }
auto value_category() const -> ValueCategory { return ValueCategory::Var; }
private:
std::optional<std::string> name_;
Nonnull<Pattern*> type_;
+3
View File
@@ -13,6 +13,7 @@
#include "executable_semantics/ast/pattern.h"
#include "executable_semantics/ast/source_location.h"
#include "executable_semantics/ast/static_scope.h"
#include "executable_semantics/ast/value_category.h"
#include "executable_semantics/common/arena.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/Compiler.h"
@@ -344,6 +345,8 @@ class Continuation : public Statement {
// and after typechecking it's guaranteed to be true.
auto has_static_type() const -> bool { return static_type_.has_value(); }
auto value_category() const -> ValueCategory { return ValueCategory::Var; }
private:
std::string continuation_variable_;
Nonnull<Block*> body_;
+25 -7
View File
@@ -13,6 +13,7 @@
#include "executable_semantics/ast/ast_node.h"
#include "executable_semantics/ast/source_location.h"
#include "executable_semantics/ast/value_category.h"
#include "executable_semantics/common/nonnull.h"
namespace Carbon {
@@ -20,12 +21,19 @@ namespace Carbon {
class Value;
// True if NodeType::ImplementsCarbonNamedEntity is valid and names a type,
// indicating that NodeType implements the NamedEntity interface. This imposes
// the following requirements on NodeType, where `node` is a const instance of
// NodeType:
// indicating that NodeType implements the NamedEntity interface, which means
// it must define the following methods, with contracts as documented.
#if 0
// Returns the static type of an IdentifierExpression that names *this.
auto static_type() const -> const Value&;
// Returns the value category of an IdentifierExpression that names *this.
auto value_category() const -> ValueCategory;
#endif
// NodeType must be derived from AstNode.
//
// - NodeType is derived from AstNode.
// - node.static_type() is well-formed and has type const Value&.
// TODO: consider turning the above documentation into real code, as sketched
// at https://godbolt.org/z/186oEozhc
template <typename T, typename = void>
static constexpr bool ImplementsNamedEntity = false;
@@ -43,9 +51,13 @@ class NamedEntityView {
NamedEntityView(Nonnull<const NodeType*> node)
// Type-erase NodeType, retaining a pointer to the base class AstNode
// and using std::function to encapsulate the ability to call
// the derived class's static_type.
: base_(node), static_type_([](const AstNode& base) -> const Value& {
// the derived class's methods.
: base_(node),
static_type_([](const AstNode& base) -> const Value& {
return llvm::cast<NodeType>(base).static_type();
}),
value_category_([](const AstNode& base) -> ValueCategory {
return llvm::cast<NodeType>(base).value_category();
}) {}
NamedEntityView(const NamedEntityView&) = default;
@@ -59,6 +71,11 @@ class NamedEntityView {
// Returns node->static_type()
auto static_type() const -> const Value& { return static_type_(*base_); }
// Returns node->value_category()
auto value_category() const -> ValueCategory {
return value_category_(*base_);
}
friend auto operator==(const NamedEntityView& lhs,
const NamedEntityView& rhs) {
return lhs.base_ == rhs.base_;
@@ -72,6 +89,7 @@ class NamedEntityView {
private:
Nonnull<const AstNode*> base_;
std::function<const Value&(const AstNode&)> static_type_;
std::function<ValueCategory(const AstNode&)> value_category_;
};
// Maps the names visible in a given scope to the entities they name.
+22
View File
@@ -0,0 +1,22 @@
// 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_VALUE_CATEGORY_H_
#define EXECUTABLE_SEMANTICS_AST_VALUE_CATEGORY_H_
namespace Carbon {
// The value category of a Carbon expression indicates whether it evaluates
// to a variable or a value. A variable can be mutated, and can have its
// address taken, whereas a value cannot.
enum class ValueCategory {
// A variable. This roughly corresponds to a C/C++ lvalue.
Var,
// A value. This roughly corresponds to a C/C++ rvalue.
Let,
};
} // namespace Carbon
#endif // EXECUTABLE_SEMANTICS_AST_VALUE_CATEGORY_H_