mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 19:11:09 +01:00
Use resolved names in typechecker (#974)
As a byproduct, replace NamedEntity with a type-erasing wrapper NamedEntityView, eliminate virtual inheritance from the AST, and eliminate interfaces from gen_rtti.
This commit is contained in:
@@ -93,6 +93,7 @@ cc_library(
|
||||
deps = [
|
||||
":ast_node",
|
||||
":paren_contents",
|
||||
":static_scope",
|
||||
"//common:indirect_value",
|
||||
"//common:ostream",
|
||||
"//executable_semantics/common:arena",
|
||||
|
||||
@@ -35,8 +35,6 @@ namespace Carbon {
|
||||
// The definitions of `InheritsFromFoo` and `FooKind` are generated from
|
||||
// ast_rtti.txt, and are implicitly provided by this header.
|
||||
//
|
||||
// When inheriting from this class, the inheritance must me marked `virtual`.
|
||||
//
|
||||
// TODO: To support generic traversal, add children() method, and ensure that
|
||||
// all AstNodes are reachable from a root AstNode.
|
||||
class AstNode {
|
||||
@@ -75,40 +73,4 @@ class AstNode {
|
||||
|
||||
} // namespace Carbon
|
||||
|
||||
// Ensure that LLVM casts from AstNode use dynamic_cast, because static_cast
|
||||
// doesn't work with a virtual base class.
|
||||
namespace llvm {
|
||||
template <typename To>
|
||||
struct cast_convert_val<To, const Carbon::AstNode*, const Carbon::AstNode*> {
|
||||
using ResultType = typename cast_retty<To, const Carbon::AstNode*>::ret_type;
|
||||
static auto doit(const Carbon::AstNode* node) -> ResultType {
|
||||
return dynamic_cast<ResultType>(node);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename To>
|
||||
struct cast_convert_val<To, Carbon::AstNode*, Carbon::AstNode*> {
|
||||
using ResultType = typename cast_retty<To, Carbon::AstNode*>::ret_type;
|
||||
static auto doit(Carbon::AstNode* node) -> ResultType {
|
||||
return dynamic_cast<ResultType>(node);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename To>
|
||||
struct cast_convert_val<To, const Carbon::AstNode, const Carbon::AstNode> {
|
||||
using ResultType = typename cast_retty<To, const Carbon::AstNode>::ret_type;
|
||||
static auto doit(const Carbon::AstNode& node) -> ResultType {
|
||||
return dynamic_cast<ResultType>(node);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename To>
|
||||
struct cast_convert_val<To, Carbon::AstNode, Carbon::AstNode> {
|
||||
using ResultType = typename cast_retty<To, Carbon::AstNode>::ret_type;
|
||||
static auto doit(Carbon::AstNode& node) -> ResultType {
|
||||
return dynamic_cast<ResultType>(node);
|
||||
}
|
||||
};
|
||||
} // namespace llvm
|
||||
|
||||
#endif // EXECUTABLE_SEMANTICS_AST_AST_NODE_H_
|
||||
|
||||
@@ -3,19 +3,18 @@
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
root class AstNode;
|
||||
interface class NamedEntity : AstNode;
|
||||
abstract class Pattern : AstNode;
|
||||
class AutoPattern : Pattern;
|
||||
class BindingPattern : Pattern, NamedEntity;
|
||||
class BindingPattern : Pattern;
|
||||
class TuplePattern : Pattern;
|
||||
class AlternativePattern : Pattern;
|
||||
class ExpressionPattern : Pattern;
|
||||
abstract class Declaration : AstNode;
|
||||
class FunctionDeclaration : Declaration, NamedEntity;
|
||||
class ClassDeclaration : Declaration, NamedEntity;
|
||||
class ChoiceDeclaration : Declaration, NamedEntity;
|
||||
class FunctionDeclaration : Declaration;
|
||||
class ClassDeclaration : Declaration;
|
||||
class ChoiceDeclaration : Declaration;
|
||||
class VariableDeclaration : Declaration;
|
||||
class GenericBinding : AstNode, NamedEntity;
|
||||
class GenericBinding : AstNode;
|
||||
class AlternativeSignature : AstNode;
|
||||
abstract class Statement : AstNode;
|
||||
class ExpressionStatement : Statement;
|
||||
@@ -28,7 +27,7 @@ abstract class Statement : AstNode;
|
||||
class Break : Statement;
|
||||
class Continue : Statement;
|
||||
class Match : Statement;
|
||||
class Continuation : Statement, NamedEntity;
|
||||
class Continuation : Statement;
|
||||
class Run : Statement;
|
||||
class Await : Statement;
|
||||
abstract class Expression : AstNode;
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Carbon {
|
||||
// every concrete derived class must have a corresponding enumerator
|
||||
// in `Kind`; see https://llvm.org/docs/HowToSetUpLLVMStyleRTTI.html for
|
||||
// details.
|
||||
class Declaration : public virtual AstNode {
|
||||
class Declaration : public AstNode {
|
||||
public:
|
||||
~Declaration() override = 0;
|
||||
|
||||
@@ -65,7 +65,8 @@ class Declaration : public virtual AstNode {
|
||||
// Constructs a Declaration representing syntax at the given line number.
|
||||
// `kind` must be the enumerator corresponding to the most-derived type being
|
||||
// constructed.
|
||||
Declaration() = default;
|
||||
Declaration(AstNodeKind kind, SourceLocation source_loc)
|
||||
: AstNode(kind, source_loc) {}
|
||||
|
||||
private:
|
||||
std::optional<Nonnull<const Value*>> static_type_;
|
||||
@@ -73,8 +74,10 @@ class Declaration : public virtual AstNode {
|
||||
|
||||
// TODO: expand the kinds of things that can be deduced parameters.
|
||||
// For now, only generic parameters are supported.
|
||||
struct GenericBinding : public virtual AstNode, public NamedEntity {
|
||||
class GenericBinding : public AstNode {
|
||||
public:
|
||||
using ImplementsCarbonNamedEntity = void;
|
||||
|
||||
GenericBinding(SourceLocation source_loc, std::string name,
|
||||
Nonnull<Expression*> type)
|
||||
: AstNode(AstNodeKind::GenericBinding, source_loc),
|
||||
@@ -188,14 +191,16 @@ class ReturnTerm {
|
||||
SourceLocation source_loc_;
|
||||
};
|
||||
|
||||
class FunctionDeclaration : public Declaration, public NamedEntity {
|
||||
class FunctionDeclaration : public Declaration {
|
||||
public:
|
||||
using ImplementsCarbonNamedEntity = void;
|
||||
|
||||
FunctionDeclaration(SourceLocation source_loc, std::string name,
|
||||
std::vector<Nonnull<GenericBinding*>> deduced_params,
|
||||
Nonnull<TuplePattern*> param_pattern,
|
||||
ReturnTerm return_term,
|
||||
std::optional<Nonnull<Block*>> body)
|
||||
: AstNode(AstNodeKind::FunctionDeclaration, source_loc),
|
||||
: Declaration(AstNodeKind::FunctionDeclaration, source_loc),
|
||||
name_(std::move(name)),
|
||||
deduced_parameters_(std::move(deduced_params)),
|
||||
param_pattern_(param_pattern),
|
||||
@@ -231,11 +236,13 @@ class FunctionDeclaration : public Declaration, public NamedEntity {
|
||||
std::optional<Nonnull<Block*>> body_;
|
||||
};
|
||||
|
||||
class ClassDeclaration : public Declaration, public NamedEntity {
|
||||
class ClassDeclaration : public Declaration {
|
||||
public:
|
||||
using ImplementsCarbonNamedEntity = void;
|
||||
|
||||
ClassDeclaration(SourceLocation source_loc, std::string name,
|
||||
std::vector<Nonnull<Member*>> members)
|
||||
: AstNode(AstNodeKind::ClassDeclaration, source_loc),
|
||||
: Declaration(AstNodeKind::ClassDeclaration, source_loc),
|
||||
name_(std::move(name)),
|
||||
members_(std::move(members)) {}
|
||||
|
||||
@@ -251,7 +258,7 @@ class ClassDeclaration : public Declaration, public NamedEntity {
|
||||
std::vector<Nonnull<Member*>> members_;
|
||||
};
|
||||
|
||||
class AlternativeSignature : public virtual AstNode {
|
||||
class AlternativeSignature : public AstNode {
|
||||
public:
|
||||
AlternativeSignature(SourceLocation source_loc, std::string name,
|
||||
Nonnull<Expression*> signature)
|
||||
@@ -274,11 +281,13 @@ class AlternativeSignature : public virtual AstNode {
|
||||
Nonnull<Expression*> signature_;
|
||||
};
|
||||
|
||||
class ChoiceDeclaration : public Declaration, public NamedEntity {
|
||||
class ChoiceDeclaration : public Declaration {
|
||||
public:
|
||||
using ImplementsCarbonNamedEntity = void;
|
||||
|
||||
ChoiceDeclaration(SourceLocation source_loc, std::string name,
|
||||
std::vector<Nonnull<AlternativeSignature*>> alternatives)
|
||||
: AstNode(AstNodeKind::ChoiceDeclaration, source_loc),
|
||||
: Declaration(AstNodeKind::ChoiceDeclaration, source_loc),
|
||||
name_(std::move(name)),
|
||||
alternatives_(std::move(alternatives)) {}
|
||||
|
||||
@@ -306,7 +315,7 @@ class VariableDeclaration : public Declaration {
|
||||
VariableDeclaration(SourceLocation source_loc,
|
||||
Nonnull<BindingPattern*> binding,
|
||||
Nonnull<Expression*> initializer)
|
||||
: AstNode(AstNodeKind::VariableDeclaration, source_loc),
|
||||
: Declaration(AstNodeKind::VariableDeclaration, source_loc),
|
||||
binding_(binding),
|
||||
initializer_(initializer) {}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "executable_semantics/ast/ast_node.h"
|
||||
#include "executable_semantics/ast/paren_contents.h"
|
||||
#include "executable_semantics/ast/source_location.h"
|
||||
#include "executable_semantics/ast/static_scope.h"
|
||||
#include "executable_semantics/common/arena.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
@@ -21,9 +22,8 @@
|
||||
namespace Carbon {
|
||||
|
||||
class Value;
|
||||
class NamedEntity;
|
||||
|
||||
class Expression : public virtual AstNode {
|
||||
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
|
||||
@@ -76,7 +76,8 @@ class Expression : public virtual AstNode {
|
||||
// Constructs an Expression representing syntax at the given line number.
|
||||
// `kind` must be the enumerator corresponding to the most-derived type being
|
||||
// constructed.
|
||||
Expression() = default;
|
||||
Expression(AstNodeKind kind, SourceLocation source_loc)
|
||||
: AstNode(kind, source_loc) {}
|
||||
|
||||
private:
|
||||
std::optional<Nonnull<const Value*>> static_type_;
|
||||
@@ -121,7 +122,7 @@ auto ToString(Operator op) -> std::string_view;
|
||||
class IdentifierExpression : public Expression {
|
||||
public:
|
||||
explicit IdentifierExpression(SourceLocation source_loc, std::string name)
|
||||
: AstNode(AstNodeKind::IdentifierExpression, source_loc),
|
||||
: Expression(AstNodeKind::IdentifierExpression, source_loc),
|
||||
name_(std::move(name)) {}
|
||||
|
||||
static auto classof(const AstNode* node) -> bool {
|
||||
@@ -130,15 +131,15 @@ class IdentifierExpression : public Expression {
|
||||
|
||||
auto name() const -> const std::string& { return name_; }
|
||||
|
||||
// Returns the NamedEntity this identifier refers to. Cannot be called before
|
||||
// name resolution.
|
||||
auto named_entity() const -> const NamedEntity& { return **named_entity_; }
|
||||
// Returns the NamedEntityView this identifier refers to. Cannot be called
|
||||
// before name resolution.
|
||||
auto named_entity() const -> const NamedEntityView& { return *named_entity_; }
|
||||
|
||||
// Sets the value returned by named_entity. Can be called only once,
|
||||
// during name resolution.
|
||||
void set_named_entity(Nonnull<const NamedEntity*> named_entity) {
|
||||
void set_named_entity(NamedEntityView named_entity) {
|
||||
CHECK(!named_entity_.has_value());
|
||||
named_entity_ = named_entity;
|
||||
named_entity_ = std::move(named_entity);
|
||||
}
|
||||
|
||||
// Returns true if set_named_entity has been called. Should be used only
|
||||
@@ -148,7 +149,7 @@ class IdentifierExpression : public Expression {
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
std::optional<Nonnull<const NamedEntity*>> named_entity_;
|
||||
std::optional<NamedEntityView> named_entity_;
|
||||
};
|
||||
|
||||
class FieldAccessExpression : public Expression {
|
||||
@@ -156,7 +157,7 @@ class FieldAccessExpression : public Expression {
|
||||
explicit FieldAccessExpression(SourceLocation source_loc,
|
||||
Nonnull<Expression*> aggregate,
|
||||
std::string field)
|
||||
: AstNode(AstNodeKind::FieldAccessExpression, source_loc),
|
||||
: Expression(AstNodeKind::FieldAccessExpression, source_loc),
|
||||
aggregate_(aggregate),
|
||||
field_(std::move(field)) {}
|
||||
|
||||
@@ -178,7 +179,7 @@ class IndexExpression : public Expression {
|
||||
explicit IndexExpression(SourceLocation source_loc,
|
||||
Nonnull<Expression*> aggregate,
|
||||
Nonnull<Expression*> offset)
|
||||
: AstNode(AstNodeKind::IndexExpression, source_loc),
|
||||
: Expression(AstNodeKind::IndexExpression, source_loc),
|
||||
aggregate_(aggregate),
|
||||
offset_(offset) {}
|
||||
|
||||
@@ -199,7 +200,7 @@ class IndexExpression : public Expression {
|
||||
class IntLiteral : public Expression {
|
||||
public:
|
||||
explicit IntLiteral(SourceLocation source_loc, int value)
|
||||
: AstNode(AstNodeKind::IntLiteral, source_loc), value_(value) {}
|
||||
: Expression(AstNodeKind::IntLiteral, source_loc), value_(value) {}
|
||||
|
||||
static auto classof(const AstNode* node) -> bool {
|
||||
return InheritsFromIntLiteral(node->kind());
|
||||
@@ -214,7 +215,7 @@ class IntLiteral : public Expression {
|
||||
class BoolLiteral : public Expression {
|
||||
public:
|
||||
explicit BoolLiteral(SourceLocation source_loc, bool value)
|
||||
: AstNode(AstNodeKind::BoolLiteral, source_loc), value_(value) {}
|
||||
: Expression(AstNodeKind::BoolLiteral, source_loc), value_(value) {}
|
||||
|
||||
static auto classof(const AstNode* node) -> bool {
|
||||
return InheritsFromBoolLiteral(node->kind());
|
||||
@@ -229,7 +230,7 @@ class BoolLiteral : public Expression {
|
||||
class StringLiteral : public Expression {
|
||||
public:
|
||||
explicit StringLiteral(SourceLocation source_loc, std::string value)
|
||||
: AstNode(AstNodeKind::StringLiteral, source_loc),
|
||||
: Expression(AstNodeKind::StringLiteral, source_loc),
|
||||
value_(std::move(value)) {}
|
||||
|
||||
static auto classof(const AstNode* node) -> bool {
|
||||
@@ -245,7 +246,7 @@ class StringLiteral : public Expression {
|
||||
class StringTypeLiteral : public Expression {
|
||||
public:
|
||||
explicit StringTypeLiteral(SourceLocation source_loc)
|
||||
: AstNode(AstNodeKind::StringTypeLiteral, source_loc) {}
|
||||
: Expression(AstNodeKind::StringTypeLiteral, source_loc) {}
|
||||
|
||||
static auto classof(const AstNode* node) -> bool {
|
||||
return InheritsFromStringTypeLiteral(node->kind());
|
||||
@@ -259,7 +260,7 @@ class TupleLiteral : public Expression {
|
||||
|
||||
explicit TupleLiteral(SourceLocation source_loc,
|
||||
std::vector<Nonnull<Expression*>> fields)
|
||||
: AstNode(AstNodeKind::TupleLiteral, source_loc),
|
||||
: Expression(AstNodeKind::TupleLiteral, source_loc),
|
||||
fields_(std::move(fields)) {}
|
||||
|
||||
static auto classof(const AstNode* node) -> bool {
|
||||
@@ -285,7 +286,8 @@ class StructLiteral : public Expression {
|
||||
public:
|
||||
explicit StructLiteral(SourceLocation loc,
|
||||
std::vector<FieldInitializer> fields)
|
||||
: AstNode(AstNodeKind::StructLiteral, loc), fields_(std::move(fields)) {
|
||||
: Expression(AstNodeKind::StructLiteral, loc),
|
||||
fields_(std::move(fields)) {
|
||||
CHECK(!fields_.empty())
|
||||
<< "`{}` is represented as a StructTypeLiteral, not a StructLiteral.";
|
||||
}
|
||||
@@ -311,7 +313,7 @@ class StructTypeLiteral : public Expression {
|
||||
|
||||
explicit StructTypeLiteral(SourceLocation loc,
|
||||
std::vector<FieldInitializer> fields)
|
||||
: AstNode(AstNodeKind::StructTypeLiteral, loc),
|
||||
: Expression(AstNodeKind::StructTypeLiteral, loc),
|
||||
fields_(std::move(fields)) {}
|
||||
|
||||
static auto classof(const AstNode* node) -> bool {
|
||||
@@ -330,7 +332,7 @@ class PrimitiveOperatorExpression : public Expression {
|
||||
explicit PrimitiveOperatorExpression(
|
||||
SourceLocation source_loc, Operator op,
|
||||
std::vector<Nonnull<Expression*>> arguments)
|
||||
: AstNode(AstNodeKind::PrimitiveOperatorExpression, source_loc),
|
||||
: Expression(AstNodeKind::PrimitiveOperatorExpression, source_loc),
|
||||
op_(op),
|
||||
arguments_(std::move(arguments)) {}
|
||||
|
||||
@@ -356,7 +358,7 @@ class CallExpression : public Expression {
|
||||
explicit CallExpression(SourceLocation source_loc,
|
||||
Nonnull<Expression*> function,
|
||||
Nonnull<Expression*> argument)
|
||||
: AstNode(AstNodeKind::CallExpression, source_loc),
|
||||
: Expression(AstNodeKind::CallExpression, source_loc),
|
||||
function_(function),
|
||||
argument_(argument) {}
|
||||
|
||||
@@ -379,7 +381,7 @@ class FunctionTypeLiteral : public Expression {
|
||||
explicit FunctionTypeLiteral(SourceLocation source_loc,
|
||||
Nonnull<Expression*> parameter,
|
||||
Nonnull<Expression*> return_type)
|
||||
: AstNode(AstNodeKind::FunctionTypeLiteral, source_loc),
|
||||
: Expression(AstNodeKind::FunctionTypeLiteral, source_loc),
|
||||
parameter_(parameter),
|
||||
return_type_(return_type) {}
|
||||
|
||||
@@ -400,7 +402,7 @@ class FunctionTypeLiteral : public Expression {
|
||||
class BoolTypeLiteral : public Expression {
|
||||
public:
|
||||
explicit BoolTypeLiteral(SourceLocation source_loc)
|
||||
: AstNode(AstNodeKind::BoolTypeLiteral, source_loc) {}
|
||||
: Expression(AstNodeKind::BoolTypeLiteral, source_loc) {}
|
||||
|
||||
static auto classof(const AstNode* node) -> bool {
|
||||
return InheritsFromBoolTypeLiteral(node->kind());
|
||||
@@ -410,7 +412,7 @@ class BoolTypeLiteral : public Expression {
|
||||
class IntTypeLiteral : public Expression {
|
||||
public:
|
||||
explicit IntTypeLiteral(SourceLocation source_loc)
|
||||
: AstNode(AstNodeKind::IntTypeLiteral, source_loc) {}
|
||||
: Expression(AstNodeKind::IntTypeLiteral, source_loc) {}
|
||||
|
||||
static auto classof(const AstNode* node) -> bool {
|
||||
return InheritsFromIntTypeLiteral(node->kind());
|
||||
@@ -420,7 +422,7 @@ class IntTypeLiteral : public Expression {
|
||||
class ContinuationTypeLiteral : public Expression {
|
||||
public:
|
||||
explicit ContinuationTypeLiteral(SourceLocation source_loc)
|
||||
: AstNode(AstNodeKind::ContinuationTypeLiteral, source_loc) {}
|
||||
: Expression(AstNodeKind::ContinuationTypeLiteral, source_loc) {}
|
||||
|
||||
static auto classof(const AstNode* node) -> bool {
|
||||
return InheritsFromContinuationTypeLiteral(node->kind());
|
||||
@@ -430,7 +432,7 @@ class ContinuationTypeLiteral : public Expression {
|
||||
class TypeTypeLiteral : public Expression {
|
||||
public:
|
||||
explicit TypeTypeLiteral(SourceLocation source_loc)
|
||||
: AstNode(AstNodeKind::TypeTypeLiteral, source_loc) {}
|
||||
: Expression(AstNodeKind::TypeTypeLiteral, source_loc) {}
|
||||
|
||||
static auto classof(const AstNode* node) -> bool {
|
||||
return InheritsFromTypeTypeLiteral(node->kind());
|
||||
@@ -446,7 +448,7 @@ class IntrinsicExpression : public Expression {
|
||||
explicit IntrinsicExpression(std::string_view intrinsic_name,
|
||||
Nonnull<TupleLiteral*> args,
|
||||
SourceLocation source_loc)
|
||||
: AstNode(AstNodeKind::IntrinsicExpression, source_loc),
|
||||
: Expression(AstNodeKind::IntrinsicExpression, source_loc),
|
||||
intrinsic_(FindIntrinsic(intrinsic_name, source_loc)),
|
||||
args_(args) {}
|
||||
|
||||
@@ -480,7 +482,7 @@ class UnimplementedExpression : public Expression {
|
||||
template <typename... Children>
|
||||
UnimplementedExpression(SourceLocation source_loc, std::string label,
|
||||
Children... children)
|
||||
: AstNode(AstNodeKind::UnimplementedExpression, source_loc),
|
||||
: Expression(AstNodeKind::UnimplementedExpression, source_loc),
|
||||
label_(std::move(label)) {
|
||||
AddChildren(children...);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace Carbon {
|
||||
// every concrete derived class must have a corresponding enumerator
|
||||
// in `Kind`; see https://llvm.org/docs/HowToSetUpLLVMStyleRTTI.html for
|
||||
// details.
|
||||
class Member : public virtual AstNode {
|
||||
class Member : public AstNode {
|
||||
public:
|
||||
~Member() override = 0;
|
||||
|
||||
@@ -43,13 +43,14 @@ class Member : public virtual AstNode {
|
||||
}
|
||||
|
||||
protected:
|
||||
Member() = default;
|
||||
Member(AstNodeKind kind, SourceLocation source_loc)
|
||||
: AstNode(kind, source_loc) {}
|
||||
};
|
||||
|
||||
class FieldMember : public Member {
|
||||
public:
|
||||
FieldMember(SourceLocation source_loc, Nonnull<BindingPattern*> binding)
|
||||
: AstNode(AstNodeKind::FieldMember, source_loc), binding_(binding) {}
|
||||
: Member(AstNodeKind::FieldMember, source_loc), binding_(binding) {}
|
||||
|
||||
static auto classof(const AstNode* node) -> bool {
|
||||
return InheritsFromFieldMember(node->kind());
|
||||
|
||||
@@ -89,7 +89,7 @@ static auto RequireFieldAccess(Nonnull<Expression*> alternative)
|
||||
AlternativePattern::AlternativePattern(SourceLocation source_loc,
|
||||
Nonnull<Expression*> alternative,
|
||||
Nonnull<TuplePattern*> arguments)
|
||||
: AstNode(AstNodeKind::AlternativePattern, source_loc),
|
||||
: Pattern(AstNodeKind::AlternativePattern, source_loc),
|
||||
choice_type_(&RequireFieldAccess(alternative).aggregate()),
|
||||
alternative_name_(RequireFieldAccess(alternative).field()),
|
||||
arguments_(arguments) {}
|
||||
|
||||
@@ -29,7 +29,7 @@ class Value;
|
||||
// every concrete derived class must have a corresponding enumerator
|
||||
// in `Kind`; see https://llvm.org/docs/HowToSetUpLLVMStyleRTTI.html for
|
||||
// details.
|
||||
class Pattern : public virtual AstNode {
|
||||
class Pattern : public AstNode {
|
||||
public:
|
||||
Pattern(const Pattern&) = delete;
|
||||
auto operator=(const Pattern&) -> Pattern& = delete;
|
||||
@@ -76,7 +76,8 @@ class Pattern : public virtual AstNode {
|
||||
// Constructs a Pattern representing syntax at the given line number.
|
||||
// `kind` must be the enumerator corresponding to the most-derived type being
|
||||
// constructed.
|
||||
Pattern() = default;
|
||||
Pattern(AstNodeKind kind, SourceLocation source_loc)
|
||||
: AstNode(kind, source_loc) {}
|
||||
|
||||
private:
|
||||
std::optional<Nonnull<const Value*>> static_type_;
|
||||
@@ -87,7 +88,7 @@ class Pattern : public virtual AstNode {
|
||||
class AutoPattern : public Pattern {
|
||||
public:
|
||||
explicit AutoPattern(SourceLocation source_loc)
|
||||
: AstNode(AstNodeKind::AutoPattern, source_loc) {}
|
||||
: Pattern(AstNodeKind::AutoPattern, source_loc) {}
|
||||
|
||||
static auto classof(const AstNode* node) -> bool {
|
||||
return InheritsFromAutoPattern(node->kind());
|
||||
@@ -96,11 +97,13 @@ class AutoPattern : public Pattern {
|
||||
|
||||
// A pattern that matches a value of a specified type, and optionally binds
|
||||
// a name to it.
|
||||
class BindingPattern : public Pattern, public NamedEntity {
|
||||
class BindingPattern : public Pattern {
|
||||
public:
|
||||
using ImplementsCarbonNamedEntity = void;
|
||||
|
||||
BindingPattern(SourceLocation source_loc, std::optional<std::string> name,
|
||||
Nonnull<Pattern*> type)
|
||||
: AstNode(AstNodeKind::BindingPattern, source_loc),
|
||||
: Pattern(AstNodeKind::BindingPattern, source_loc),
|
||||
name_(std::move(name)),
|
||||
type_(type) {}
|
||||
|
||||
@@ -124,7 +127,7 @@ class BindingPattern : public Pattern, public NamedEntity {
|
||||
class TuplePattern : public Pattern {
|
||||
public:
|
||||
TuplePattern(SourceLocation source_loc, std::vector<Nonnull<Pattern*>> fields)
|
||||
: AstNode(AstNodeKind::TuplePattern, source_loc),
|
||||
: Pattern(AstNodeKind::TuplePattern, source_loc),
|
||||
fields_(std::move(fields)) {}
|
||||
|
||||
static auto classof(const AstNode* node) -> bool {
|
||||
@@ -170,7 +173,7 @@ class AlternativePattern : public Pattern {
|
||||
Nonnull<Expression*> choice_type,
|
||||
std::string alternative_name,
|
||||
Nonnull<TuplePattern*> arguments)
|
||||
: AstNode(AstNodeKind::AlternativePattern, source_loc),
|
||||
: Pattern(AstNodeKind::AlternativePattern, source_loc),
|
||||
choice_type_(choice_type),
|
||||
alternative_name_(std::move(alternative_name)),
|
||||
arguments_(arguments) {}
|
||||
@@ -204,7 +207,7 @@ class AlternativePattern : public Pattern {
|
||||
class ExpressionPattern : public Pattern {
|
||||
public:
|
||||
explicit ExpressionPattern(Nonnull<Expression*> expression)
|
||||
: AstNode(AstNodeKind::ExpressionPattern, expression->source_loc()),
|
||||
: Pattern(AstNodeKind::ExpressionPattern, expression->source_loc()),
|
||||
expression_(expression) {}
|
||||
|
||||
static auto classof(const AstNode* node) -> bool {
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Carbon {
|
||||
|
||||
class FunctionDeclaration;
|
||||
|
||||
class Statement : public virtual AstNode {
|
||||
class Statement : public AstNode {
|
||||
public:
|
||||
~Statement() override = 0;
|
||||
|
||||
@@ -39,13 +39,14 @@ class Statement : public virtual AstNode {
|
||||
}
|
||||
|
||||
protected:
|
||||
Statement() = default;
|
||||
Statement(AstNodeKind kind, SourceLocation source_loc)
|
||||
: AstNode(kind, source_loc) {}
|
||||
};
|
||||
|
||||
class Block : public Statement {
|
||||
public:
|
||||
Block(SourceLocation source_loc, std::vector<Nonnull<Statement*>> statements)
|
||||
: AstNode(AstNodeKind::Block, source_loc),
|
||||
: Statement(AstNodeKind::Block, source_loc),
|
||||
statements_(std::move(statements)) {}
|
||||
|
||||
static auto classof(const AstNode* node) -> bool {
|
||||
@@ -67,7 +68,7 @@ class ExpressionStatement : public Statement {
|
||||
public:
|
||||
ExpressionStatement(SourceLocation source_loc,
|
||||
Nonnull<Expression*> expression)
|
||||
: AstNode(AstNodeKind::ExpressionStatement, source_loc),
|
||||
: Statement(AstNodeKind::ExpressionStatement, source_loc),
|
||||
expression_(expression) {}
|
||||
|
||||
static auto classof(const AstNode* node) -> bool {
|
||||
@@ -85,7 +86,7 @@ class Assign : public Statement {
|
||||
public:
|
||||
Assign(SourceLocation source_loc, Nonnull<Expression*> lhs,
|
||||
Nonnull<Expression*> rhs)
|
||||
: AstNode(AstNodeKind::Assign, source_loc), lhs_(lhs), rhs_(rhs) {}
|
||||
: Statement(AstNodeKind::Assign, source_loc), lhs_(lhs), rhs_(rhs) {}
|
||||
|
||||
static auto classof(const AstNode* node) -> bool {
|
||||
return InheritsFromAssign(node->kind());
|
||||
@@ -105,7 +106,7 @@ class VariableDefinition : public Statement {
|
||||
public:
|
||||
VariableDefinition(SourceLocation source_loc, Nonnull<Pattern*> pattern,
|
||||
Nonnull<Expression*> init)
|
||||
: AstNode(AstNodeKind::VariableDefinition, source_loc),
|
||||
: Statement(AstNodeKind::VariableDefinition, source_loc),
|
||||
pattern_(pattern),
|
||||
init_(init) {}
|
||||
|
||||
@@ -127,7 +128,7 @@ class If : public Statement {
|
||||
public:
|
||||
If(SourceLocation source_loc, Nonnull<Expression*> condition,
|
||||
Nonnull<Block*> then_block, std::optional<Nonnull<Block*>> else_block)
|
||||
: AstNode(AstNodeKind::If, source_loc),
|
||||
: Statement(AstNodeKind::If, source_loc),
|
||||
condition_(condition),
|
||||
then_block_(then_block),
|
||||
else_block_(else_block) {}
|
||||
@@ -157,7 +158,7 @@ class Return : public Statement {
|
||||
: Return(source_loc, arena->New<TupleLiteral>(source_loc), true) {}
|
||||
Return(SourceLocation source_loc, Nonnull<Expression*> expression,
|
||||
bool is_omitted_expression)
|
||||
: AstNode(AstNodeKind::Return, source_loc),
|
||||
: Statement(AstNodeKind::Return, source_loc),
|
||||
expression_(expression),
|
||||
is_omitted_expression_(is_omitted_expression) {}
|
||||
|
||||
@@ -194,7 +195,7 @@ class While : public Statement {
|
||||
public:
|
||||
While(SourceLocation source_loc, Nonnull<Expression*> condition,
|
||||
Nonnull<Block*> body)
|
||||
: AstNode(AstNodeKind::While, source_loc),
|
||||
: Statement(AstNodeKind::While, source_loc),
|
||||
condition_(condition),
|
||||
body_(body) {}
|
||||
|
||||
@@ -215,7 +216,7 @@ class While : public Statement {
|
||||
class Break : public Statement {
|
||||
public:
|
||||
explicit Break(SourceLocation source_loc)
|
||||
: AstNode(AstNodeKind::Break, source_loc) {}
|
||||
: Statement(AstNodeKind::Break, source_loc) {}
|
||||
|
||||
static auto classof(const AstNode* node) -> bool {
|
||||
return InheritsFromBreak(node->kind());
|
||||
@@ -242,7 +243,7 @@ class Break : public Statement {
|
||||
class Continue : public Statement {
|
||||
public:
|
||||
explicit Continue(SourceLocation source_loc)
|
||||
: AstNode(AstNodeKind::Continue, source_loc) {}
|
||||
: Statement(AstNodeKind::Continue, source_loc) {}
|
||||
|
||||
static auto classof(const AstNode* node) -> bool {
|
||||
return InheritsFromContinue(node->kind());
|
||||
@@ -285,7 +286,7 @@ class Match : public Statement {
|
||||
|
||||
Match(SourceLocation source_loc, Nonnull<Expression*> expression,
|
||||
std::vector<Clause> clauses)
|
||||
: AstNode(AstNodeKind::Match, source_loc),
|
||||
: Statement(AstNodeKind::Match, source_loc),
|
||||
expression_(expression),
|
||||
clauses_(std::move(clauses)) {}
|
||||
|
||||
@@ -308,11 +309,13 @@ class Match : public Statement {
|
||||
// __continuation <continuation_variable> {
|
||||
// <body>
|
||||
// }
|
||||
class Continuation : public Statement, public NamedEntity {
|
||||
class Continuation : public Statement {
|
||||
public:
|
||||
using ImplementsCarbonNamedEntity = void;
|
||||
|
||||
Continuation(SourceLocation source_loc, std::string continuation_variable,
|
||||
Nonnull<Block*> body)
|
||||
: AstNode(AstNodeKind::Continuation, source_loc),
|
||||
: Statement(AstNodeKind::Continuation, source_loc),
|
||||
continuation_variable_(std::move(continuation_variable)),
|
||||
body_(body) {}
|
||||
|
||||
@@ -353,7 +356,7 @@ class Continuation : public Statement, public NamedEntity {
|
||||
class Run : public Statement {
|
||||
public:
|
||||
Run(SourceLocation source_loc, Nonnull<Expression*> argument)
|
||||
: AstNode(AstNodeKind::Run, source_loc), argument_(argument) {}
|
||||
: Statement(AstNodeKind::Run, source_loc), argument_(argument) {}
|
||||
|
||||
static auto classof(const AstNode* node) -> bool {
|
||||
return InheritsFromRun(node->kind());
|
||||
@@ -372,7 +375,7 @@ class Run : public Statement {
|
||||
class Await : public Statement {
|
||||
public:
|
||||
explicit Await(SourceLocation source_loc)
|
||||
: AstNode(AstNodeKind::Await, source_loc) {}
|
||||
: Statement(AstNodeKind::Await, source_loc) {}
|
||||
|
||||
static auto classof(const AstNode* node) -> bool {
|
||||
return InheritsFromAwait(node->kind());
|
||||
|
||||
@@ -8,22 +8,18 @@
|
||||
|
||||
namespace Carbon {
|
||||
|
||||
NamedEntity::~NamedEntity() = default;
|
||||
|
||||
void StaticScope::Add(std::string name, Nonnull<const NamedEntity*> entity) {
|
||||
void StaticScope::Add(std::string name, NamedEntityView entity) {
|
||||
auto [it, success] = declared_names_.insert({name, entity});
|
||||
if (!success && it->second != entity) {
|
||||
FATAL_COMPILATION_ERROR(entity->source_loc())
|
||||
FATAL_COMPILATION_ERROR(entity.base().source_loc())
|
||||
<< "Duplicate name `" << name << "` also found at "
|
||||
<< it->second->source_loc();
|
||||
<< it->second.base().source_loc();
|
||||
}
|
||||
}
|
||||
|
||||
auto StaticScope::Resolve(const std::string& name,
|
||||
SourceLocation source_loc) const
|
||||
-> Nonnull<const NamedEntity*> {
|
||||
std::optional<Nonnull<const NamedEntity*>> result =
|
||||
TryResolve(name, source_loc);
|
||||
SourceLocation source_loc) const -> NamedEntityView {
|
||||
std::optional<NamedEntityView> result = TryResolve(name, source_loc);
|
||||
if (!result.has_value()) {
|
||||
FATAL_COMPILATION_ERROR(source_loc) << "could not resolve '" << name << "'";
|
||||
}
|
||||
@@ -32,19 +28,20 @@ auto StaticScope::Resolve(const std::string& name,
|
||||
|
||||
auto StaticScope::TryResolve(const std::string& name,
|
||||
SourceLocation source_loc) const
|
||||
-> std::optional<Nonnull<const NamedEntity*>> {
|
||||
-> std::optional<NamedEntityView> {
|
||||
auto it = declared_names_.find(name);
|
||||
if (it != declared_names_.end()) {
|
||||
return it->second;
|
||||
}
|
||||
std::optional<Nonnull<const NamedEntity*>> result;
|
||||
std::optional<NamedEntityView> result;
|
||||
for (Nonnull<const StaticScope*> parent : parent_scopes_) {
|
||||
auto parent_result = parent->TryResolve(name, source_loc);
|
||||
if (parent_result.has_value() && result.has_value() &&
|
||||
*parent_result != *result) {
|
||||
FATAL_COMPILATION_ERROR(source_loc)
|
||||
<< "'" << name << "' is ambiguous between " << (*result)->source_loc()
|
||||
<< " and " << (*parent_result)->source_loc();
|
||||
<< "'" << name << "' is ambiguous between "
|
||||
<< result->base().source_loc() << " and "
|
||||
<< parent_result->base().source_loc();
|
||||
}
|
||||
result = parent_result;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#ifndef EXECUTABLE_SEMANTICS_AST_STATIC_SCOPE_H_
|
||||
#define EXECUTABLE_SEMANTICS_AST_STATIC_SCOPE_H_
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <variant>
|
||||
@@ -16,16 +17,61 @@
|
||||
|
||||
namespace Carbon {
|
||||
|
||||
class NamedEntity : public virtual AstNode {
|
||||
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:
|
||||
//
|
||||
// - NodeType is derived from AstNode.
|
||||
// - node.static_type() is well-formed and has type const Value&.
|
||||
template <typename T, typename = void>
|
||||
static constexpr bool ImplementsNamedEntity = false;
|
||||
|
||||
template <typename T>
|
||||
static constexpr bool
|
||||
ImplementsNamedEntity<T, typename T::ImplementsCarbonNamedEntity> = true;
|
||||
|
||||
// Non-owning type-erased wrapper around a const NodeType* `node`, where
|
||||
// NodeType implements the NamedEntity interface.
|
||||
class NamedEntityView {
|
||||
public:
|
||||
~NamedEntity() override = 0;
|
||||
template <typename NodeType,
|
||||
typename = std::enable_if_t<ImplementsNamedEntity<NodeType>>>
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
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& {
|
||||
return llvm::cast<NodeType>(base).static_type();
|
||||
}) {}
|
||||
|
||||
NamedEntity() = default;
|
||||
NamedEntityView(const NamedEntityView&) = default;
|
||||
NamedEntityView(NamedEntityView&&) = default;
|
||||
auto operator=(const NamedEntityView&) -> NamedEntityView& = default;
|
||||
auto operator=(NamedEntityView&&) -> NamedEntityView& = default;
|
||||
|
||||
// TODO: This is unused, but is intended for casts after lookup.
|
||||
auto kind() const -> NamedEntityKind {
|
||||
return static_cast<NamedEntityKind>(root_kind());
|
||||
// Returns `node` as an instance of the base class AstNode.
|
||||
auto base() const -> const AstNode& { return *base_; }
|
||||
|
||||
// Returns node->static_type()
|
||||
auto static_type() const -> const Value& { return static_type_(*base_); }
|
||||
|
||||
friend auto operator==(const NamedEntityView& lhs,
|
||||
const NamedEntityView& rhs) {
|
||||
return lhs.base_ == rhs.base_;
|
||||
}
|
||||
|
||||
friend auto operator!=(const NamedEntityView& lhs,
|
||||
const NamedEntityView& rhs) {
|
||||
return lhs.base_ != rhs.base_;
|
||||
}
|
||||
|
||||
private:
|
||||
Nonnull<const AstNode*> base_;
|
||||
std::function<const Value&(const AstNode&)> static_type_;
|
||||
};
|
||||
|
||||
// Maps the names visible in a given scope to the entities they name.
|
||||
@@ -35,7 +81,7 @@ class StaticScope {
|
||||
public:
|
||||
// Defines `name` to be `entity` in this scope, or reports a compilation error
|
||||
// if `name` is already defined to be a different entity in this scope.
|
||||
void Add(std::string name, Nonnull<const NamedEntity*> entity);
|
||||
void Add(std::string name, NamedEntityView entity);
|
||||
|
||||
// Make `parent` a parent of this scope.
|
||||
// REQUIRES: `parent` is not already a parent of this scope.
|
||||
@@ -47,17 +93,17 @@ class StaticScope {
|
||||
// scope, or reports a compilation error at `source_loc` there isn't exactly
|
||||
// one such definition.
|
||||
auto Resolve(const std::string& name, SourceLocation source_loc) const
|
||||
-> Nonnull<const NamedEntity*>;
|
||||
-> NamedEntityView;
|
||||
|
||||
private:
|
||||
// Equivalent to Resolve, but returns `nullopt` instead of raising an error
|
||||
// if no definition can be found. Still raises a compilation error if more
|
||||
// than one definition is found.
|
||||
auto TryResolve(const std::string& name, SourceLocation source_loc) const
|
||||
-> std::optional<Nonnull<const NamedEntity*>>;
|
||||
-> std::optional<NamedEntityView>;
|
||||
|
||||
// Maps locally declared names to their entities.
|
||||
std::unordered_map<std::string, Nonnull<const NamedEntity*>> declared_names_;
|
||||
std::unordered_map<std::string, NamedEntityView> declared_names_;
|
||||
|
||||
// A list of scopes used for name lookup within this scope.
|
||||
std::vector<Nonnull<StaticScope*>> parent_scopes_;
|
||||
|
||||
Reference in New Issue
Block a user