Addr Keyword Implementation (#1255)

* Implement addr keyword

* Add files that were deleted during merge

Some files got deleted during merging trunk because of the executable
semantics rename.

* Implement changes from code review.

Major changes:
- Rename AddrBindingPattern to AddrPattern
- Fix AddrPattern related changes in fuzzing

* Update documentation for GetField

* Fix AddPattern according to @zygoloid's suggestions

* Apply @zygoloid's changes to method comment

* Add a multi-component field example

* Incorporate AST changes to fuzzer corpus

* Refactor the deduced_param_list grammar rule

Suggested by @zygoloid
This commit is contained in:
Darshal Shetty
2022-06-01 13:51:37 -04:00
committed by GitHub
parent f0572ee110
commit e4a2d0f047
47 changed files with 610 additions and 99 deletions
+6 -1
View File
@@ -179,6 +179,10 @@ message VarPattern {
optional Pattern pattern = 1;
}
message AddrPattern {
optional BindingPattern binding_pattern = 1;
}
message Pattern {
oneof kind {
BindingPattern binding_pattern = 1;
@@ -188,6 +192,7 @@ message Pattern {
AutoPattern auto_pattern = 5;
VarPattern var_pattern = 6;
GenericBinding generic_binding = 7;
AddrPattern addr_pattern = 8;
}
}
@@ -286,7 +291,7 @@ message ReturnTerm {
message FunctionDeclaration {
optional string name = 1;
repeated GenericBinding deduced_parameters = 2;
optional BindingPattern me_pattern = 3;
optional Pattern me_pattern = 3;
optional TuplePattern param_pattern = 4;
optional ReturnTerm return_term = 5;
optional BlockStatement body = 6;
+6 -1
View File
@@ -425,6 +425,11 @@ static auto PatternToCarbon(const Fuzzing::Pattern& pattern,
case Fuzzing::Pattern::kGenericBinding:
GenericBindingToCarbon(pattern.generic_binding(), out);
break;
case Fuzzing::Pattern::kAddrPattern:
out << "addr ";
BindingPatternToCarbon(pattern.addr_pattern().binding_pattern(), out);
break;
}
}
@@ -598,7 +603,7 @@ static auto DeclarationToCarbon(const Fuzzing::Declaration& declaration,
if (function.has_me_pattern()) {
// This is a class method.
out << sep;
BindingPatternToCarbon(function.me_pattern(), out);
PatternToCarbon(function.me_pattern(), out);
}
out << "]";
}
+1
View File
@@ -6,6 +6,7 @@ root class AstNode;
abstract class Pattern : AstNode;
class AutoPattern : Pattern;
class VarPattern : Pattern;
class AddrPattern : Pattern;
class BindingPattern : Pattern;
class GenericBinding : Pattern;
class TuplePattern : Pattern;
+17 -6
View File
@@ -185,12 +185,13 @@ void ReturnTerm::Print(llvm::raw_ostream& out) const {
}
}
auto FunctionDeclaration::Create(
Nonnull<Arena*> arena, SourceLocation source_loc, std::string name,
std::vector<Nonnull<AstNode*>> deduced_params,
std::optional<Nonnull<BindingPattern*>> me_pattern,
Nonnull<TuplePattern*> param_pattern, ReturnTerm return_term,
std::optional<Nonnull<Block*>> body)
auto FunctionDeclaration::Create(Nonnull<Arena*> arena,
SourceLocation source_loc, std::string name,
std::vector<Nonnull<AstNode*>> deduced_params,
std::optional<Nonnull<Pattern*>> me_pattern,
Nonnull<TuplePattern*> param_pattern,
ReturnTerm return_term,
std::optional<Nonnull<Block*>> body)
-> ErrorOr<Nonnull<FunctionDeclaration*>> {
std::vector<Nonnull<GenericBinding*>> resolved_params;
// Look for the `me` parameter in the `deduced_parameters`
@@ -209,6 +210,16 @@ auto FunctionDeclaration::Create(
me_pattern = bp;
break;
}
case AstNodeKind::AddrPattern: {
Nonnull<AddrPattern*> abp = &cast<AddrPattern>(*param);
Nonnull<BindingPattern*> bp = &cast<BindingPattern>(abp->binding());
if (me_pattern.has_value() || bp->name() != "me") {
return CompilationError(source_loc)
<< "illegal binding pattern in implicit parameter list";
}
me_pattern = abp;
break;
}
default:
return CompilationError(source_loc)
<< "illegal AST node in implicit parameter list";
+5 -5
View File
@@ -104,7 +104,7 @@ class FunctionDeclaration : public Declaration {
static auto Create(Nonnull<Arena*> arena, SourceLocation source_loc,
std::string name,
std::vector<Nonnull<AstNode*>> deduced_params,
std::optional<Nonnull<BindingPattern*>> me_pattern,
std::optional<Nonnull<Pattern*>> me_pattern,
Nonnull<TuplePattern*> param_pattern,
ReturnTerm return_term,
std::optional<Nonnull<Block*>> body)
@@ -113,7 +113,7 @@ class FunctionDeclaration : public Declaration {
// Use `Create()` instead. This is public only so Arena::New() can call it.
FunctionDeclaration(SourceLocation source_loc, std::string name,
std::vector<Nonnull<GenericBinding*>> deduced_params,
std::optional<Nonnull<BindingPattern*>> me_pattern,
std::optional<Nonnull<Pattern*>> me_pattern,
Nonnull<TuplePattern*> param_pattern,
ReturnTerm return_term,
std::optional<Nonnull<Block*>> body)
@@ -139,8 +139,8 @@ class FunctionDeclaration : public Declaration {
auto deduced_parameters() -> llvm::ArrayRef<Nonnull<GenericBinding*>> {
return deduced_parameters_;
}
auto me_pattern() const -> const BindingPattern& { return **me_pattern_; }
auto me_pattern() -> BindingPattern& { return **me_pattern_; }
auto me_pattern() const -> const Pattern& { return **me_pattern_; }
auto me_pattern() -> Pattern& { return **me_pattern_; }
auto param_pattern() const -> const TuplePattern& { return *param_pattern_; }
auto param_pattern() -> TuplePattern& { return *param_pattern_; }
auto return_term() const -> const ReturnTerm& { return return_term_; }
@@ -155,7 +155,7 @@ class FunctionDeclaration : public Declaration {
private:
std::string name_;
std::vector<Nonnull<GenericBinding*>> deduced_parameters_;
std::optional<Nonnull<BindingPattern*>> me_pattern_;
std::optional<Nonnull<Pattern*>> me_pattern_;
Nonnull<TuplePattern*> param_pattern_;
ReturnTerm return_term_;
std::optional<Nonnull<Block*>> body_;
+9
View File
@@ -168,6 +168,14 @@ class SimpleMemberAccessExpression : public Expression {
auto object() const -> const Expression& { return *object_; }
auto object() -> Expression& { return *object_; }
auto member() const -> const std::string& { return member_; }
// Returns true if the field is a method that has a "me" declaration in an
// AddrPattern.
auto is_field_addr_me_method() const -> bool {
return is_field_addr_me_method_;
}
// Can only be called once, during typechecking.
void set_is_field_addr_me_method() { is_field_addr_me_method_ = true; }
// If `object` has a generic type, returns the `ImplBinding` that
// identifies its witness table. Otherwise, returns `std::nullopt`. Should not
@@ -186,6 +194,7 @@ class SimpleMemberAccessExpression : public Expression {
Nonnull<Expression*> object_;
std::string member_;
std::optional<Nonnull<const ImplBinding*>> impl_;
bool is_field_addr_me_method_ = false;
};
// A compound member access expression of the form `object.(path)`.
+8
View File
@@ -56,6 +56,9 @@ void Pattern::Print(llvm::raw_ostream& out) const {
case PatternKind::VarPattern:
out << "var" << cast<VarPattern>(*this).pattern();
break;
case PatternKind::AddrPattern:
out << "addr" << cast<AddrPattern>(*this).binding();
break;
}
}
@@ -87,6 +90,9 @@ void Pattern::PrintID(llvm::raw_ostream& out) const {
case PatternKind::VarPattern:
out << "var ...";
break;
case PatternKind::AddrPattern:
out << "addr ...";
break;
case PatternKind::ExpressionPattern:
out << "...";
break;
@@ -112,6 +118,8 @@ auto VisitNestedPatterns(const Pattern& pattern,
visitor);
case PatternKind::VarPattern:
return VisitNestedPatterns(cast<VarPattern>(pattern).pattern(), visitor);
case PatternKind::AddrPattern:
return VisitNestedPatterns(cast<AddrPattern>(pattern).binding(), visitor);
case PatternKind::BindingPattern:
case PatternKind::AutoPattern:
case PatternKind::ExpressionPattern:
+17
View File
@@ -184,6 +184,23 @@ class BindingPattern : public Pattern {
std::optional<ValueCategory> value_category_;
};
class AddrPattern : public Pattern {
public:
explicit AddrPattern(SourceLocation source_loc,
Nonnull<BindingPattern*> binding)
: Pattern(AstNodeKind::AddrPattern, source_loc), binding_(binding) {}
static auto classof(const AstNode* node) -> bool {
return InheritsFromAddrPattern(node->kind());
}
auto binding() const -> const BindingPattern& { return *binding_; }
auto binding() -> BindingPattern& { return *binding_; }
private:
Nonnull<BindingPattern*> binding_;
};
// A pattern that matches a tuple value field-wise.
class TuplePattern : public Pattern {
public:
+21 -2
View File
@@ -322,6 +322,10 @@ static auto PatternToProto(const Pattern& pattern) -> Fuzzing::Pattern {
*pattern_proto.mutable_var_pattern()->mutable_pattern() =
PatternToProto(cast<VarPattern>(pattern).pattern());
break;
case PatternKind::AddrPattern:
*pattern_proto.mutable_addr_pattern()->mutable_binding_pattern() =
BindingPatternToProto(cast<AddrPattern>(pattern).binding());
break;
}
return pattern_proto;
}
@@ -479,8 +483,23 @@ static auto DeclarationToProto(const Declaration& declaration)
GenericBindingToProto(*binding);
}
if (function.is_method()) {
*function_proto->mutable_me_pattern() =
BindingPatternToProto(function.me_pattern());
switch (function.me_pattern().kind()) {
case PatternKind::AddrPattern:
*function_proto->mutable_me_pattern() =
PatternToProto(cast<AddrPattern>(function.me_pattern()));
break;
case PatternKind::BindingPattern:
*function_proto->mutable_me_pattern() =
PatternToProto(cast<BindingPattern>(function.me_pattern()));
break;
default:
// Parser shouldn't allow me_pattern to be anything other than
// AddrPattern or BindingPattern
CARBON_FATAL() << "me_pattern in method declaration can be either "
"AddrPattern or BindingPattern. Actual pattern: "
<< function.me_pattern();
break;
}
}
*function_proto->mutable_param_pattern() =
TuplePatternToProto(function.param_pattern());
@@ -10,12 +10,14 @@ compilation_unit {
function {
name: "Add"
me_pattern {
name: "me"
type {
expression_pattern {
expression {
identifier {
name: "Self"
binding_pattern {
name: "me"
type {
expression_pattern {
expression {
identifier {
name: "Self"
}
}
}
}
@@ -51,12 +53,14 @@ compilation_unit {
function {
name: "Mul"
me_pattern {
name: "me"
type {
expression_pattern {
expression {
identifier {
name: "Self"
binding_pattern {
name: "me"
type {
expression_pattern {
expression {
identifier {
name: "Self"
}
}
}
}
@@ -113,6 +117,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -122,6 +127,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -172,6 +178,7 @@ compilation_unit {
function {
name: "Mul"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -181,6 +188,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -284,6 +292,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -294,6 +303,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -325,6 +335,7 @@ compilation_unit {
function {
name: "Scale"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -335,6 +346,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -366,6 +378,7 @@ compilation_unit {
function {
name: "Hold"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -376,6 +389,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -528,6 +542,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -538,6 +553,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -635,6 +651,7 @@ compilation_unit {
function {
name: "Scale"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -645,6 +662,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -731,6 +749,7 @@ compilation_unit {
function {
name: "Hold"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -741,6 +760,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -25,6 +25,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -35,6 +36,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -66,6 +68,7 @@ compilation_unit {
function {
name: "Scale"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -76,6 +79,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -241,6 +245,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -263,6 +268,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -384,6 +390,7 @@ compilation_unit {
function {
name: "Scale"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -406,6 +413,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -10,6 +10,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -20,6 +21,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -51,6 +53,7 @@ compilation_unit {
function {
name: "Scale"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -61,6 +64,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -146,6 +150,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -156,6 +161,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -253,6 +259,7 @@ compilation_unit {
function {
name: "Scale"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -263,6 +270,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -10,6 +10,7 @@ compilation_unit {
function {
name: "Op"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -20,6 +21,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -121,6 +123,7 @@ compilation_unit {
function {
name: "Op"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -131,6 +134,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -25,6 +25,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -35,6 +36,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -161,6 +163,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -170,6 +173,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -315,6 +319,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -325,6 +330,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -25,6 +25,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -35,6 +36,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -158,6 +160,7 @@ compilation_unit {
function {
name: "Clone"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -181,6 +184,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
}
@@ -247,6 +251,7 @@ compilation_unit {
function {
name: "SumXY"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -270,6 +275,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
}
@@ -409,6 +415,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -418,6 +425,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -10,6 +10,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -20,6 +21,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -51,6 +53,7 @@ compilation_unit {
function {
name: "Scale"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -61,6 +64,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -148,6 +152,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -158,6 +163,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -255,6 +261,7 @@ compilation_unit {
function {
name: "Scale"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -265,6 +272,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -65,6 +65,7 @@ compilation_unit {
function {
name: "GetX"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -75,6 +76,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
}
@@ -10,6 +10,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -20,6 +21,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -51,6 +53,7 @@ compilation_unit {
function {
name: "Scale"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -61,6 +64,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -146,6 +150,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -156,6 +161,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -253,6 +259,7 @@ compilation_unit {
function {
name: "Scale"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -263,6 +270,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -399,6 +407,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -409,6 +418,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -526,6 +536,7 @@ compilation_unit {
function {
name: "Scale"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -536,6 +547,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -25,6 +25,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -35,6 +36,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -66,6 +68,7 @@ compilation_unit {
function {
name: "Scale"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -76,6 +79,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -202,6 +206,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -212,6 +217,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -309,6 +315,7 @@ compilation_unit {
function {
name: "Scale"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -319,6 +326,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -25,6 +25,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -35,6 +36,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -241,6 +243,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -250,6 +253,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -25,6 +25,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -35,6 +36,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -66,6 +68,7 @@ compilation_unit {
function {
name: "Scale"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -76,6 +79,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -202,6 +206,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -212,6 +217,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -309,6 +315,7 @@ compilation_unit {
function {
name: "Scale"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -319,6 +326,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -25,6 +25,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -35,6 +36,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -66,6 +68,7 @@ compilation_unit {
function {
name: "Scale"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -76,6 +79,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -229,6 +233,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -239,6 +244,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -336,6 +342,7 @@ compilation_unit {
function {
name: "Scale"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -346,6 +353,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -25,6 +25,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -35,6 +36,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -66,6 +68,7 @@ compilation_unit {
function {
name: "Scale"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -76,6 +79,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -202,6 +206,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -212,6 +217,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -309,6 +315,7 @@ compilation_unit {
function {
name: "Scale"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -319,6 +326,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -25,6 +25,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -35,6 +36,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -161,6 +163,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -170,6 +173,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -328,6 +332,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -351,6 +356,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -10,6 +10,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -20,6 +21,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -51,6 +53,7 @@ compilation_unit {
function {
name: "Scale"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -61,6 +64,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -146,6 +150,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -156,6 +161,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -253,6 +259,7 @@ compilation_unit {
function {
name: "Scale"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -263,6 +270,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -25,6 +25,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -35,6 +36,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -390,6 +392,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -399,6 +402,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -51,12 +51,14 @@ compilation_unit {
function {
name: "GetX"
me_pattern {
name: "me"
type {
expression_pattern {
expression {
identifier {
name: "Point"
binding_pattern {
name: "me"
type {
expression_pattern {
expression {
identifier {
name: "Point"
}
}
}
}
@@ -10,6 +10,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -20,6 +21,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -51,6 +53,7 @@ compilation_unit {
function {
name: "Scale"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -61,6 +64,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -148,6 +152,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -158,6 +163,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -255,6 +261,7 @@ compilation_unit {
function {
name: "Scale"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -265,6 +272,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -25,6 +25,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -35,6 +36,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -161,6 +163,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -170,6 +173,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -328,6 +332,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -351,6 +356,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -10,6 +10,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -20,6 +21,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -51,6 +53,7 @@ compilation_unit {
function {
name: "Scale"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -61,6 +64,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -146,6 +150,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -156,6 +161,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -253,6 +259,7 @@ compilation_unit {
function {
name: "Scale"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -263,6 +270,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -78,6 +78,7 @@ compilation_unit {
function {
name: "GetX"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -101,6 +102,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
}
@@ -25,6 +25,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -35,6 +36,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -451,6 +453,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -460,6 +463,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -25,6 +25,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -35,6 +36,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -66,6 +68,7 @@ compilation_unit {
function {
name: "Scale"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -76,6 +79,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -215,6 +219,7 @@ compilation_unit {
function {
name: "Add"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -225,6 +230,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
@@ -322,6 +328,7 @@ compilation_unit {
function {
name: "Scale"
me_pattern {
binding_pattern {
name: "me"
type {
expression_pattern {
@@ -332,6 +339,7 @@ compilation_unit {
}
}
}
}
}
param_pattern {
fields {
+2 -2
View File
@@ -24,8 +24,8 @@ auto Heap::AllocateValue(Nonnull<const Value*> v) -> AllocationId {
auto Heap::Read(const Address& a, SourceLocation source_loc) const
-> ErrorOr<Nonnull<const Value*>> {
CARBON_RETURN_IF_ERROR(this->CheckAlive(a.allocation_, source_loc));
return values_[a.allocation_.index_]->GetMember(arena_, a.field_path_,
source_loc);
Nonnull<const Value*> value = values_[a.allocation_.index_];
return value->GetMember(arena_, a.field_path_, source_loc, value);
}
auto Heap::Write(const Address& a, Nonnull<const Value*> v,
+58 -23
View File
@@ -209,8 +209,8 @@ auto PatternMatch(Nonnull<const Value*> p, Nonnull<const Value*> v,
SourceLocation source_loc,
std::optional<Nonnull<RuntimeScope*>> bindings,
BindingMap& generic_args,
std::optional<Nonnull<llvm::raw_ostream*>> trace_stream)
-> bool {
std::optional<Nonnull<llvm::raw_ostream*>> trace_stream,
Nonnull<Arena*> arena) -> bool {
if (trace_stream) {
**trace_stream << "match pattern " << *p << "\nwith value " << *v << "\n";
}
@@ -223,6 +223,14 @@ auto PatternMatch(Nonnull<const Value*> p, Nonnull<const Value*> v,
}
return true;
}
case Value::Kind::AddrValue: {
const auto& addr = cast<AddrValue>(*p);
CARBON_CHECK(v->kind() == Value::Kind::LValue);
const auto& lvalue = cast<LValue>(*v);
return PatternMatch(
&addr.pattern(), arena->New<PointerValue>(lvalue.address()),
source_loc, bindings, generic_args, trace_stream, arena);
}
case Value::Kind::VariableType: {
const auto& var_type = cast<VariableType>(*p);
generic_args[&var_type.binding()] = v;
@@ -236,8 +244,8 @@ auto PatternMatch(Nonnull<const Value*> p, Nonnull<const Value*> v,
CARBON_CHECK(p_tup.elements().size() == v_tup.elements().size());
for (size_t i = 0; i < p_tup.elements().size(); ++i) {
if (!PatternMatch(p_tup.elements()[i], v_tup.elements()[i],
source_loc, bindings, generic_args,
trace_stream)) {
source_loc, bindings, generic_args, trace_stream,
arena)) {
return false;
}
} // for
@@ -255,7 +263,7 @@ auto PatternMatch(Nonnull<const Value*> p, Nonnull<const Value*> v,
v_struct.elements()[i].name);
if (!PatternMatch(p_struct.elements()[i].value,
v_struct.elements()[i].value, source_loc, bindings,
generic_args, trace_stream)) {
generic_args, trace_stream, arena)) {
return false;
}
}
@@ -271,7 +279,7 @@ auto PatternMatch(Nonnull<const Value*> p, Nonnull<const Value*> v,
return false;
}
return PatternMatch(&p_alt.argument(), &v_alt.argument(), source_loc,
bindings, generic_args, trace_stream);
bindings, generic_args, trace_stream, arena);
}
default:
CARBON_FATAL() << "expected a choice alternative in pattern, not "
@@ -283,11 +291,12 @@ auto PatternMatch(Nonnull<const Value*> p, Nonnull<const Value*> v,
const auto& p_fn = cast<FunctionType>(*p);
const auto& v_fn = cast<FunctionType>(*v);
if (!PatternMatch(&p_fn.parameters(), &v_fn.parameters(), source_loc,
bindings, generic_args, trace_stream)) {
bindings, generic_args, trace_stream, arena)) {
return false;
}
if (!PatternMatch(&p_fn.return_type(), &v_fn.return_type(),
source_loc, bindings, generic_args, trace_stream)) {
source_loc, bindings, generic_args, trace_stream,
arena)) {
return false;
}
return true;
@@ -503,6 +512,7 @@ auto Interpreter::Convert(Nonnull<const Value*> value,
case Value::Kind::ContinuationType:
case Value::Kind::VariableType:
case Value::Kind::BindingPlaceholderValue:
case Value::Kind::AddrValue:
case Value::Kind::AlternativeConstructorValue:
case Value::Kind::ContinuationValue:
case Value::Kind::StringType:
@@ -637,9 +647,9 @@ auto Interpreter::CallFunction(const CallExpression& call,
RuntimeScope function_scope(&heap_);
BindingMap generic_args;
CARBON_CHECK(PatternMatch(&function.param_pattern().value(),
converted_args, call.source_loc(),
&function_scope, generic_args, trace_stream_));
CARBON_CHECK(PatternMatch(
&function.param_pattern().value(), converted_args, call.source_loc(),
&function_scope, generic_args, trace_stream_, this->arena_));
CARBON_CHECK(function.body().has_value())
<< "Calling a function that's missing a body";
return todo_.Spawn(std::make_unique<StatementAction>(*function.body()),
@@ -657,10 +667,10 @@ auto Interpreter::CallFunction(const CallExpression& call,
BindingMap generic_args;
CARBON_CHECK(PatternMatch(&method.me_pattern().value(), m.receiver(),
call.source_loc(), &method_scope, generic_args,
trace_stream_));
trace_stream_, this->arena_));
CARBON_CHECK(PatternMatch(&method.param_pattern().value(), converted_args,
call.source_loc(), &method_scope, generic_args,
trace_stream_));
trace_stream_, this->arena_));
// Bring the class type arguments into scope.
for (const auto& [bind, val] : m.type_args()) {
method_scope.Initialize(bind, val);
@@ -681,7 +691,8 @@ auto Interpreter::CallFunction(const CallExpression& call,
RuntimeScope params_scope(&heap_);
BindingMap generic_args;
CARBON_CHECK(PatternMatch(&name.params().value(), arg, call.source_loc(),
&params_scope, generic_args, trace_stream_));
&params_scope, generic_args, trace_stream_,
this->arena_));
switch (decl.kind()) {
case DeclarationKind::ClassDeclaration: {
switch (phase()) {
@@ -804,9 +815,17 @@ auto Interpreter::StepExp() -> ErrorOr<Success> {
case ExpressionKind::SimpleMemberAccessExpression: {
const auto& access = cast<SimpleMemberAccessExpression>(exp);
if (act.pos() == 0) {
return todo_.Spawn(
std::make_unique<ExpressionAction>(&access.object()));
// { { e.f :: C, E, F} :: S, H}
// -> { { e :: [].f :: C, E, F} :: S, H}
if (access.is_field_addr_me_method()) {
return todo_.Spawn(std::make_unique<LValAction>(&access.object()));
} else {
return todo_.Spawn(
std::make_unique<ExpressionAction>(&access.object()));
}
} else {
// { { v :: [].f :: C, E, F} :: S, H}
// -> { { v_f :: C, E, F} : S, H}
if (const auto* member_name_type =
dyn_cast<TypeOfMemberName>(&access.static_type())) {
// The result is a member name, such as in `Type.field_name`. Form a
@@ -842,10 +861,18 @@ auto Interpreter::StepExp() -> ErrorOr<Success> {
witness = cast<Witness>(witness_value);
}
FieldPath::Component member(access.member(), witness);
const Value* aggregate;
if (const auto* lvalue = dyn_cast<LValue>(act.results()[0])) {
CARBON_ASSIGN_OR_RETURN(
aggregate,
this->heap_.Read(lvalue->address(), exp.source_loc()));
} else {
aggregate = act.results()[0];
}
CARBON_ASSIGN_OR_RETURN(
Nonnull<const Value*> member_value,
act.results()[0]->GetMember(arena_, FieldPath(member),
exp.source_loc()));
aggregate->GetMember(arena_, FieldPath(member), exp.source_loc(),
act.results()[0]));
return todo_.FinishAction(member_value);
}
}
@@ -892,9 +919,9 @@ auto Interpreter::StepExp() -> ErrorOr<Success> {
exp.source_loc()));
}
FieldPath::Component field(access.member().name(), witness);
CARBON_ASSIGN_OR_RETURN(
Nonnull<const Value*> member,
object->GetMember(arena_, FieldPath(field), exp.source_loc()));
CARBON_ASSIGN_OR_RETURN(Nonnull<const Value*> member,
object->GetMember(arena_, FieldPath(field),
exp.source_loc(), object));
return todo_.FinishAction(member);
}
}
@@ -1148,6 +1175,14 @@ auto Interpreter::StepPattern() -> ErrorOr<Success> {
} else {
return todo_.FinishAction(act.results()[0]);
}
case PatternKind::AddrPattern:
const auto& addr = cast<AddrPattern>(pattern);
if (act.pos() == 0) {
return todo_.Spawn(std::make_unique<PatternAction>(&addr.binding()));
} else {
return todo_.FinishAction(arena_->New<AddrValue>(act.results()[0]));
}
break;
}
}
@@ -1181,7 +1216,7 @@ auto Interpreter::StepStmt() -> ErrorOr<Success> {
Convert(act.results()[0], &c.pattern().static_type(),
stmt.source_loc()));
if (PatternMatch(&c.pattern().value(), val, stmt.source_loc(), &matches,
generic_args, trace_stream_)) {
generic_args, trace_stream_, this->arena_)) {
// Ensure we don't process any more clauses.
act.set_pos(match_stmt.clauses().size() + 1);
todo_.MergeScope(std::move(matches));
@@ -1262,7 +1297,7 @@ auto Interpreter::StepStmt() -> ErrorOr<Success> {
RuntimeScope matches(&heap_);
BindingMap generic_args;
CARBON_CHECK(PatternMatch(p, v, stmt.source_loc(), &matches,
generic_args, trace_stream_))
generic_args, trace_stream_, this->arena_))
<< stmt.source_loc()
<< ": internal error in variable definition, match failed";
todo_.MergeScope(std::move(matches));
+2 -1
View File
@@ -53,7 +53,8 @@ auto InterpPattern(Nonnull<const Pattern*> p, Nonnull<Arena*> arena,
[[nodiscard]] auto PatternMatch(
Nonnull<const Value*> p, Nonnull<const Value*> v, SourceLocation source_loc,
std::optional<Nonnull<RuntimeScope*>> bindings, BindingMap& generic_args,
std::optional<Nonnull<llvm::raw_ostream*>> trace_stream) -> bool;
std::optional<Nonnull<llvm::raw_ostream*>> trace_stream,
Nonnull<Arena*> arena) -> bool;
} // namespace Carbon
+4
View File
@@ -242,6 +242,10 @@ static auto ResolveNames(Pattern& pattern, StaticScope& enclosing_scope)
CARBON_RETURN_IF_ERROR(
ResolveNames(cast<VarPattern>(pattern).pattern(), enclosing_scope));
break;
case PatternKind::AddrPattern:
CARBON_RETURN_IF_ERROR(
ResolveNames(cast<AddrPattern>(pattern).binding(), enclosing_scope));
break;
}
return Success();
}
+61 -14
View File
@@ -77,6 +77,7 @@ static auto IsTypeOfType(Nonnull<const Value*> value) -> bool {
case Value::Kind::NominalClassValue:
case Value::Kind::AlternativeValue:
case Value::Kind::BindingPlaceholderValue:
case Value::Kind::AddrValue:
case Value::Kind::AlternativeConstructorValue:
case Value::Kind::ContinuationValue:
case Value::Kind::StringValue:
@@ -129,6 +130,7 @@ static auto IsType(Nonnull<const Value*> value, bool concrete = false) -> bool {
case Value::Kind::NominalClassValue:
case Value::Kind::AlternativeValue:
case Value::Kind::BindingPlaceholderValue:
case Value::Kind::AddrValue:
case Value::Kind::AlternativeConstructorValue:
case Value::Kind::ContinuationValue:
case Value::Kind::StringValue:
@@ -145,7 +147,6 @@ static auto IsType(Nonnull<const Value*> value, bool concrete = false) -> bool {
case Value::Kind::BoolType:
case Value::Kind::TypeType:
case Value::Kind::FunctionType:
case Value::Kind::PointerType:
case Value::Kind::StructType:
case Value::Kind::NominalClassType:
case Value::Kind::InterfaceType:
@@ -169,6 +170,9 @@ static auto IsType(Nonnull<const Value*> value, bool concrete = false) -> bool {
}
return true;
}
case Value::Kind::PointerType: {
return IsType(&cast<PointerType>(*value).type(), concrete);
}
}
}
@@ -438,7 +442,7 @@ auto TypeChecker::GetBuiltinInterfaceType(SourceLocation source_loc,
if (has_arguments) {
TupleValue args(interface.arguments);
if (!PatternMatch(&iface_decl->params().value()->value(), &args, source_loc,
std::nullopt, bindings, trace_stream_)) {
std::nullopt, bindings, trace_stream_, this->arena_)) {
return bad_builtin();
}
}
@@ -703,6 +707,7 @@ auto TypeChecker::ArgumentDeduction(
case Value::Kind::NominalClassValue:
case Value::Kind::AlternativeValue:
case Value::Kind::BindingPlaceholderValue:
case Value::Kind::AddrValue:
case Value::Kind::AlternativeConstructorValue:
case Value::Kind::ContinuationValue:
case Value::Kind::StringValue: {
@@ -814,6 +819,7 @@ auto TypeChecker::Substitute(
case Value::Kind::NominalClassValue:
case Value::Kind::AlternativeValue:
case Value::Kind::BindingPlaceholderValue:
case Value::Kind::AddrValue:
case Value::Kind::AlternativeConstructorValue:
case Value::Kind::ContinuationValue:
case Value::Kind::StringValue:
@@ -1141,9 +1147,24 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
case DeclarationKind::VariableDeclaration:
access.set_value_category(access.object().value_category());
break;
case DeclarationKind::FunctionDeclaration:
case DeclarationKind::FunctionDeclaration: {
auto func_decl = cast<FunctionDeclaration>(*member);
if (func_decl->is_method() && func_decl->me_pattern().kind() ==
PatternKind::AddrPattern) {
access.set_is_field_addr_me_method();
CARBON_RETURN_IF_ERROR(
ExpectType(e->source_loc(), "method access",
&func_decl->me_pattern().static_type(),
&access.object().static_type(), &impl_scope));
if (access.object().value_category() != ValueCategory::Var) {
return CompilationError(e->source_loc())
<< "method " << access.member()
<< " requires its receiver to be an lvalue";
}
}
access.set_value_category(ValueCategory::Let);
break;
}
default:
CARBON_FATAL() << "member " << access.member()
<< " is not a field or method";
@@ -1512,8 +1533,9 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
op.set_value_category(ValueCategory::Var);
return Success();
case Operator::Ptr:
CARBON_RETURN_IF_ERROR(ExpectExactType(
e->source_loc(), "*", arena_->New<TypeType>(), ts[0]));
CARBON_RETURN_IF_ERROR(ExpectType(e->source_loc(), "*",
arena_->New<TypeType>(), ts[0],
&impl_scope));
op.set_static_type(arena_->New<TypeType>());
op.set_value_category(ValueCategory::Let);
return Success();
@@ -1805,7 +1827,8 @@ auto TypeChecker::TypeCheckPattern(
} else {
BindingMap generic_args;
if (!PatternMatch(type, *expected, binding.type().source_loc(),
std::nullopt, generic_args, trace_stream_)) {
std::nullopt, generic_args, trace_stream_,
this->arena_)) {
return CompilationError(binding.type().source_loc())
<< "Type pattern '" << *type
<< "' does not match actual type '" << **expected << "'";
@@ -1921,17 +1944,40 @@ auto TypeChecker::TypeCheckPattern(
SetValue(p, expr_value);
return Success();
}
case PatternKind::VarPattern:
auto& let_var_pattern = cast<VarPattern>(*p);
case PatternKind::VarPattern: {
auto& var_pattern = cast<VarPattern>(*p);
CARBON_RETURN_IF_ERROR(
TypeCheckPattern(&let_var_pattern.pattern(), expected, impl_scope,
let_var_pattern.value_category()));
let_var_pattern.set_static_type(&let_var_pattern.pattern().static_type());
CARBON_RETURN_IF_ERROR(TypeCheckPattern(&var_pattern.pattern(), expected,
impl_scope,
var_pattern.value_category()));
var_pattern.set_static_type(&var_pattern.pattern().static_type());
CARBON_ASSIGN_OR_RETURN(
Nonnull<const Value*> pattern_value,
InterpPattern(&let_var_pattern, arena_, trace_stream_));
SetValue(&let_var_pattern, pattern_value);
InterpPattern(&var_pattern, arena_, trace_stream_));
SetValue(&var_pattern, pattern_value);
return Success();
}
case PatternKind::AddrPattern:
std::optional<Nonnull<const Value*>> expected_ptr;
auto& addr_pattern = cast<AddrPattern>(*p);
if (expected) {
expected_ptr = arena_->New<PointerType>(expected.value());
}
CARBON_RETURN_IF_ERROR(TypeCheckPattern(&addr_pattern.binding(),
expected_ptr, impl_scope,
enclosing_value_category));
if (auto* inner_binding_type =
dyn_cast<PointerType>(&addr_pattern.binding().static_type())) {
addr_pattern.set_static_type(&inner_binding_type->type());
} else {
return CompilationError(addr_pattern.source_loc())
<< "Type associated with addr must be a pointer type.";
}
CARBON_ASSIGN_OR_RETURN(
Nonnull<const Value*> pattern_value,
InterpPattern(&addr_pattern, arena_, trace_stream_));
SetValue(&addr_pattern, pattern_value);
return Success();
}
}
@@ -2605,6 +2651,7 @@ static bool IsValidTypeForAliasTarget(Nonnull<const Value*> type) {
case Value::Kind::ParameterizedEntityName:
case Value::Kind::MemberName:
case Value::Kind::BindingPlaceholderValue:
case Value::Kind::AddrValue:
case Value::Kind::AlternativeConstructorValue:
case Value::Kind::ContinuationValue:
case Value::Kind::StringValue:
+13 -5
View File
@@ -31,7 +31,7 @@ auto StructValue::FindField(const std::string& name) const
static auto GetMember(Nonnull<Arena*> arena, Nonnull<const Value*> v,
const FieldPath::Component& field,
SourceLocation source_loc)
SourceLocation source_loc, Nonnull<const Value*> me_value)
-> ErrorOr<Nonnull<const Value*>> {
const std::string& f = field.name();
@@ -93,7 +93,7 @@ static auto GetMember(Nonnull<Arena*> arena, Nonnull<const Value*> v,
} else if ((*func)->declaration().is_method()) {
// Found a method. Turn it into a bound method.
const FunctionValue& m = cast<FunctionValue>(**func);
return arena->New<BoundMethodValue>(&m.declaration(), &object,
return arena->New<BoundMethodValue>(&m.declaration(), me_value,
class_type.type_args(),
class_type.witnesses());
} else {
@@ -131,12 +131,13 @@ static auto GetMember(Nonnull<Arena*> arena, Nonnull<const Value*> v,
}
auto Value::GetMember(Nonnull<Arena*> arena, const FieldPath& path,
SourceLocation source_loc) const
SourceLocation source_loc,
Nonnull<const Value*> me_value) const
-> ErrorOr<Nonnull<const Value*>> {
Nonnull<const Value*> value(this);
for (const FieldPath::Component& field : path.components_) {
CARBON_ASSIGN_OR_RETURN(value,
Carbon::GetMember(arena, value, field, source_loc));
CARBON_ASSIGN_OR_RETURN(
value, Carbon::GetMember(arena, value, field, source_loc, me_value));
}
return value;
}
@@ -216,6 +217,11 @@ void Value::Print(llvm::raw_ostream& out) const {
out << ">";
break;
}
case Value::Kind::AddrValue: {
const auto& addr = cast<AddrValue>(*this);
out << "Addr<" << addr.pattern() << ">";
break;
}
case Value::Kind::AlternativeValue: {
const auto& alt = cast<AlternativeValue>(*this);
out << "alt " << alt.choice_name() << "." << alt.alt_name() << " "
@@ -569,6 +575,7 @@ auto TypeEqual(Nonnull<const Value*> t1, Nonnull<const Value*> t2) -> bool {
case Value::Kind::PointerValue:
case Value::Kind::LValue:
case Value::Kind::BindingPlaceholderValue:
case Value::Kind::AddrValue:
case Value::Kind::ContinuationValue:
case Value::Kind::ParameterizedEntityName:
case Value::Kind::MemberName:
@@ -679,6 +686,7 @@ auto ValueEqual(Nonnull<const Value*> v1, Nonnull<const Value*> v2) -> bool {
case Value::Kind::NominalClassValue:
case Value::Kind::AlternativeValue:
case Value::Kind::BindingPlaceholderValue:
case Value::Kind::AddrValue:
case Value::Kind::AlternativeConstructorValue:
case Value::Kind::ContinuationValue:
case Value::Kind::PointerValue:
+22 -2
View File
@@ -61,6 +61,7 @@ class Value {
ParameterizedEntityName,
MemberName,
BindingPlaceholderValue,
AddrValue,
AlternativeConstructorValue,
ContinuationValue, // A first-class continuation value.
StringType,
@@ -80,9 +81,12 @@ class Value {
LLVM_DUMP_METHOD void Dump() const { Print(llvm::errs()); }
// Returns the sub-Value specified by `path`, which must be a valid field
// path for *this.
// path for *this. If the sub-Value is a method and its me_pattern is an
// AddrPattern, then pass the LValue representing the receiver as `me_value`,
// otherwise pass `*this`.
auto GetMember(Nonnull<Arena*> arena, const FieldPath& path,
SourceLocation source_loc) const
SourceLocation source_loc,
Nonnull<const Value*> me_value) const
-> ErrorOr<Nonnull<const Value*>>;
// Returns a copy of *this, but with the sub-Value specified by `path`
@@ -395,6 +399,22 @@ class BindingPlaceholderValue : public Value {
std::optional<ValueNodeView> value_node_;
};
// Value for addr pattern
class AddrValue : public Value {
public:
explicit AddrValue(Nonnull<const Value*> pattern)
: Value(Kind::AddrValue), pattern_(pattern) {}
static auto classof(const Value* value) -> bool {
return value->kind() == Kind::AddrValue;
}
auto pattern() const -> const Value& { return *pattern_; }
private:
Nonnull<const Value*> pattern_;
};
// The int type.
class IntType : public Value {
public:
+2
View File
@@ -33,6 +33,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
%s AFTER_OPERAND
/* table-begin */
ADDR "addr"
ALIAS "alias"
AMPERSAND "&"
AND "and"
@@ -138,6 +139,7 @@ string_literal \"([^\\\"\n\v\f\r]|\\.)*\"
%}
/* table-begin */
{ADDR} { return SIMPLE_TOKEN(ADDR); }
{ALIAS} { return SIMPLE_TOKEN(ALIAS); }
{AMPERSAND} { return SIMPLE_TOKEN(AMPERSAND); }
{AND} { return SIMPLE_TOKEN(AND); }
+18 -19
View File
@@ -142,6 +142,7 @@
%type <Nonnull<Expression*>> if_expression
%type <Nonnull<Expression*>> expression
%type <Nonnull<GenericBinding*>> generic_binding
%type <Nonnull<Pattern*>> deduced_param
%type <std::vector<Nonnull<AstNode*>>> deduced_params
%type <std::vector<Nonnull<AstNode*>>> impl_deduced_params
%type <std::vector<Nonnull<AstNode*>>> deduced_param_list
@@ -155,7 +156,7 @@
%type <std::vector<FieldInitializer>> struct_type_literal_contents
%type <Nonnull<TupleLiteral*>> tuple
%type <std::string> binding_lhs
%type <std::optional<Nonnull<BindingPattern*>>> receiver
%type <std::optional<Nonnull<Pattern*>>> receiver
%type <Nonnull<BindingPattern*>> variable_declaration
%type <ParenContents<Expression>> paren_expression_base
%type <ParenContents<Expression>> paren_expression_contents
@@ -174,6 +175,7 @@
%token
// Most tokens have their spelling defined in lexer.lpp.
// table-begin
ADDR
ALIAS
AMPERSAND
AND
@@ -797,27 +799,22 @@ generic_binding:
$$ = arena->New<GenericBinding>(context.source_loc(), std::move($1), $3);
}
;
deduced_param:
generic_binding
{ $$ = $1; }
| variable_declaration
{ $$ = $1; }
| ADDR variable_declaration
{ $$ = arena->New<AddrPattern>(context.source_loc(), $2); }
;
deduced_param_list:
// Empty
{ $$ = std::vector<Nonnull<AstNode*>>(); }
| generic_binding
{ $$ = {}; }
| deduced_param
{ $$ = {$1}; }
| deduced_param_list COMMA deduced_param
{
$$ = std::vector<Nonnull<AstNode*>>();
$$.push_back($1);
}
| deduced_param_list COMMA generic_binding
{
$$ = $1;
$$.push_back($3);
}
| variable_declaration
{
$$ = std::vector<Nonnull<AstNode*>>();
$$.push_back($1);
}
| deduced_param_list COMMA variable_declaration
{
$$ = $1;
$$ = $1; // TODO: can we std::move here?
$$.push_back($3);
}
;
@@ -838,6 +835,8 @@ receiver:
{ $$ = std::nullopt; }
| LEFT_CURLY_BRACE variable_declaration RIGHT_CURLY_BRACE
{ $$ = $2; }
| LEFT_CURLY_BRACE ADDR variable_declaration RIGHT_CURLY_BRACE
{ $$ = arena->New<AddrPattern>(context.source_loc(), $3); }
;
function_declaration:
FN identifier deduced_params receiver maybe_empty_tuple_pattern return_term block
+37
View File
@@ -0,0 +1,37 @@
// 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
//
// RUN: %{not} %{explorer} %s 2>&1 | \
// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes=false %s
// RUN: %{not} %{explorer} --parser_debug --trace_file=- %s 2>&1 | \
// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes %s
// AUTOUPDATE: %{explorer} %s
// CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/addr/fail-method-let.carbon:32: method GetSetX requires its receiver to be an lvalue
package ExplorerTest api;
class Point {
fn Origin() -> Point {
return {.x = 0, .y = 0};
}
fn GetSetX[addr me: Point*](x: i32) -> i32 {
var old: auto = (*me).x;
(*me).x = x;
return old;
}
var x: i32;
var y: i32;
}
fn Main() -> i32 {
let p: Point = Point.Origin();
var x: auto = p.GetSetX(42);
if (p.x == 42) {
return x;
}
return 1;
}
+41
View File
@@ -0,0 +1,41 @@
// 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
//
// RUN: %{not} %{explorer} %s 2>&1 | \
// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes=false %s
// RUN: %{not} %{explorer} --parser_debug --trace_file=- %s 2>&1 | \
// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes %s
// AUTOUPDATE: %{explorer} %s
// CHECK: COMPILATION ERROR: {{.*}}/explorer/testdata/addr/fail-method-me-type.carbon:36: type error in method access: 'class Point' is not implicitly convertible to 'class Shape'
package ExplorerTest api;
class Shape {
var x: i32;
}
class Point {
fn Origin() -> Point {
return {.x = 0, .y = 0};
}
fn GetSetX[addr me: Shape*](x: i32) -> i32 {
var old: auto = (*me).x;
(*me).x = x;
return old;
}
var x: i32;
var y: i32;
}
fn Main() -> i32 {
var p: Point = Point.Origin();
var x: auto = p.GetSetX(42);
if (p.x == 42) {
return x;
}
return 1;
}
+37
View File
@@ -0,0 +1,37 @@
// 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
//
// RUN: %{explorer} %s 2>&1 | \
// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes=false %s
// RUN: %{explorer} --parser_debug --trace_file=- %s 2>&1 | \
// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes %s
// AUTOUPDATE: %{explorer} %s
// CHECK: result: 0
package ExplorerTest api;
class Point {
fn Origin() -> Point {
return {.x = 0, .y = 0};
}
fn GetSetX[addr me: Point*](x: i32) -> i32 {
var old: auto = (*me).x;
(*me).x = x;
return old;
}
var x: i32;
var y: i32;
}
fn Main() -> i32 {
var p: Point = Point.Origin();
var x: auto = p.GetSetX(42);
if (p.x == 42) {
return x;
}
return 1;
}
+37
View File
@@ -0,0 +1,37 @@
// 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
//
// RUN: %{explorer} %s 2>&1 | \
// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes=false %s
// RUN: %{explorer} --parser_debug --trace_file=- %s 2>&1 | \
// RUN: %{FileCheck} --match-full-lines --allow-unused-prefixes %s
// AUTOUPDATE: %{explorer} %s
// CHECK: result: 0
package ExplorerTest api;
class B {
var x: i32;
fn GetSetX[addr me: Self*](x: i32) -> i32 {
var oldX: auto = (*me).x;
(*me).x = x;
return oldX;
}
}
class A {
var b: B;
}
fn Main() -> i32 {
var b: B = {.x = 0};
var a: A = {.b = b};
var x: auto = a.b.GetSetX(42);
if (a.b.x == 42) {
return x;
}
return 1;
}
Executable → Regular
View File