Quellcode durchsuchen

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
Darshal Shetty vor 3 Jahren
Ursprung
Commit
e4a2d0f047
47 geänderte Dateien mit 610 neuen und 99 gelöschten Zeilen
  1. 6 1
      common/fuzzing/carbon.proto
  2. 6 1
      common/fuzzing/proto_to_carbon.cpp
  3. 1 0
      explorer/ast/ast_rtti.txt
  4. 17 6
      explorer/ast/declaration.cpp
  5. 5 5
      explorer/ast/declaration.h
  6. 9 0
      explorer/ast/expression.h
  7. 8 0
      explorer/ast/pattern.cpp
  8. 17 0
      explorer/ast/pattern.h
  9. 21 2
      explorer/fuzzing/ast_to_proto.cpp
  10. 32 12
      explorer/fuzzing/fuzzer_corpus/017a765e283355ded618ed95de5da4e3f2dd4b52.textproto
  11. 8 0
      explorer/fuzzing/fuzzer_corpus/0ee3d72e3cab1b0907f04f35b2d33fb946ab32c9.textproto
  12. 8 0
      explorer/fuzzing/fuzzer_corpus/1844089b39db6518836420fcb6a5d37b3e99424f.textproto
  13. 4 0
      explorer/fuzzing/fuzzer_corpus/2caf42dcf02bff184fa653bf36054b9d83704e30.textproto
  14. 6 0
      explorer/fuzzing/fuzzer_corpus/32e0eb929035d7c53b3d8566ac48ef0c3b82b32e.textproto
  15. 8 0
      explorer/fuzzing/fuzzer_corpus/5357de7edef4e3bff993192d9538493ae80f5fa8.textproto
  16. 8 0
      explorer/fuzzing/fuzzer_corpus/5e4bce73c210e45269126773f257d95d4d269072.textproto
  17. 2 0
      explorer/fuzzing/fuzzer_corpus/63979179f0b4279dbf7a98a3a7b9837393d43e8a.textproto
  18. 12 0
      explorer/fuzzing/fuzzer_corpus/6c86299b17c54466628587a48c2ec0e9d3029fc7.textproto
  19. 8 0
      explorer/fuzzing/fuzzer_corpus/6f589265e1e503d2e01043d6a332026d1693095e.textproto
  20. 4 0
      explorer/fuzzing/fuzzer_corpus/72624c04b293dcee7ecc0129b6e196195ca84332.textproto
  21. 8 0
      explorer/fuzzing/fuzzer_corpus/7b7e24319e8f63e6c3e99f8cbc81da7e9e47390a.textproto
  22. 8 0
      explorer/fuzzing/fuzzer_corpus/81b5d416277f5b28d98ac9b175f73389d9857655.textproto
  23. 8 0
      explorer/fuzzing/fuzzer_corpus/8fa92df904a230ee4b0ecf1362170a2551aec98b.textproto
  24. 6 0
      explorer/fuzzing/fuzzer_corpus/9a79849f37e616453382dcd0ff273c080d3b4f7f.textproto
  25. 8 0
      explorer/fuzzing/fuzzer_corpus/9bb0b055035cb4965aa9432c34bdb1be0f8c3b80.textproto
  26. 4 0
      explorer/fuzzing/fuzzer_corpus/a04fd176eb32a1a2500bf298f4f5deb37b9fa406.textproto
  27. 8 6
      explorer/fuzzing/fuzzer_corpus/a88508d94032d0429d1cba11c1df90deb142c155.textproto
  28. 8 0
      explorer/fuzzing/fuzzer_corpus/d44b1b3f6ff018d0829e0d73f551d0144b39e638.textproto
  29. 6 0
      explorer/fuzzing/fuzzer_corpus/f0249ef671686916199dbce1467d741102a68717.textproto
  30. 8 0
      explorer/fuzzing/fuzzer_corpus/f986b7976441ebd0928d8f4d13c6ff2be6a05f50.textproto
  31. 2 0
      explorer/fuzzing/fuzzer_corpus/fc5f5e4f348579cedbecae8dccafc9f9dae68237.textproto
  32. 4 0
      explorer/fuzzing/fuzzer_corpus/fda984fd483f47ca29fd55b54173f77ef690b4ee.textproto
  33. 8 0
      explorer/fuzzing/fuzzer_corpus/fe3c5db046e0dae74603f2c43ed1af68eea9a6ae.textproto
  34. 2 2
      explorer/interpreter/heap.cpp
  35. 58 23
      explorer/interpreter/interpreter.cpp
  36. 2 1
      explorer/interpreter/interpreter.h
  37. 4 0
      explorer/interpreter/resolve_names.cpp
  38. 61 14
      explorer/interpreter/type_checker.cpp
  39. 13 5
      explorer/interpreter/value.cpp
  40. 22 2
      explorer/interpreter/value.h
  41. 2 0
      explorer/syntax/lexer.lpp
  42. 18 19
      explorer/syntax/parser.ypp
  43. 37 0
      explorer/testdata/addr/fail-method-let.carbon
  44. 41 0
      explorer/testdata/addr/fail-method-me-type.carbon
  45. 37 0
      explorer/testdata/addr/method.carbon
  46. 37 0
      explorer/testdata/addr/nested-method.carbon
  47. 0 0
      explorer/update_checks.py

+ 6 - 1
common/fuzzing/carbon.proto

@@ -179,6 +179,10 @@ message VarPattern {
   optional Pattern pattern = 1;
   optional Pattern pattern = 1;
 }
 }
 
 
+message AddrPattern {
+  optional BindingPattern binding_pattern = 1;
+}
+
 message Pattern {
 message Pattern {
   oneof kind {
   oneof kind {
     BindingPattern binding_pattern = 1;
     BindingPattern binding_pattern = 1;
@@ -188,6 +192,7 @@ message Pattern {
     AutoPattern auto_pattern = 5;
     AutoPattern auto_pattern = 5;
     VarPattern var_pattern = 6;
     VarPattern var_pattern = 6;
     GenericBinding generic_binding = 7;
     GenericBinding generic_binding = 7;
+    AddrPattern addr_pattern = 8;
   }
   }
 }
 }
 
 
@@ -286,7 +291,7 @@ message ReturnTerm {
 message FunctionDeclaration {
 message FunctionDeclaration {
   optional string name = 1;
   optional string name = 1;
   repeated GenericBinding deduced_parameters = 2;
   repeated GenericBinding deduced_parameters = 2;
-  optional BindingPattern me_pattern = 3;
+  optional Pattern me_pattern = 3;
   optional TuplePattern param_pattern = 4;
   optional TuplePattern param_pattern = 4;
   optional ReturnTerm return_term = 5;
   optional ReturnTerm return_term = 5;
   optional BlockStatement body = 6;
   optional BlockStatement body = 6;

+ 6 - 1
common/fuzzing/proto_to_carbon.cpp

@@ -425,6 +425,11 @@ static auto PatternToCarbon(const Fuzzing::Pattern& pattern,
     case Fuzzing::Pattern::kGenericBinding:
     case Fuzzing::Pattern::kGenericBinding:
       GenericBindingToCarbon(pattern.generic_binding(), out);
       GenericBindingToCarbon(pattern.generic_binding(), out);
       break;
       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()) {
         if (function.has_me_pattern()) {
           // This is a class method.
           // This is a class method.
           out << sep;
           out << sep;
-          BindingPatternToCarbon(function.me_pattern(), out);
+          PatternToCarbon(function.me_pattern(), out);
         }
         }
         out << "]";
         out << "]";
       }
       }

+ 1 - 0
explorer/ast/ast_rtti.txt

@@ -6,6 +6,7 @@ root class AstNode;
 abstract class Pattern : AstNode;
 abstract class Pattern : AstNode;
   class AutoPattern : Pattern;
   class AutoPattern : Pattern;
   class VarPattern : Pattern;
   class VarPattern : Pattern;
+  class AddrPattern : Pattern;
   class BindingPattern : Pattern;
   class BindingPattern : Pattern;
   class GenericBinding : Pattern;
   class GenericBinding : Pattern;
   class TuplePattern : Pattern;
   class TuplePattern : Pattern;

+ 17 - 6
explorer/ast/declaration.cpp

@@ -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*>> {
     -> ErrorOr<Nonnull<FunctionDeclaration*>> {
   std::vector<Nonnull<GenericBinding*>> resolved_params;
   std::vector<Nonnull<GenericBinding*>> resolved_params;
   // Look for the `me` parameter in the `deduced_parameters`
   // Look for the `me` parameter in the `deduced_parameters`
@@ -209,6 +210,16 @@ auto FunctionDeclaration::Create(
         me_pattern = bp;
         me_pattern = bp;
         break;
         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:
       default:
         return CompilationError(source_loc)
         return CompilationError(source_loc)
                << "illegal AST node in implicit parameter list";
                << "illegal AST node in implicit parameter list";

+ 5 - 5
explorer/ast/declaration.h

@@ -104,7 +104,7 @@ class FunctionDeclaration : public Declaration {
   static auto Create(Nonnull<Arena*> arena, SourceLocation source_loc,
   static auto Create(Nonnull<Arena*> arena, SourceLocation source_loc,
                      std::string name,
                      std::string name,
                      std::vector<Nonnull<AstNode*>> deduced_params,
                      std::vector<Nonnull<AstNode*>> deduced_params,
-                     std::optional<Nonnull<BindingPattern*>> me_pattern,
+                     std::optional<Nonnull<Pattern*>> me_pattern,
                      Nonnull<TuplePattern*> param_pattern,
                      Nonnull<TuplePattern*> param_pattern,
                      ReturnTerm return_term,
                      ReturnTerm return_term,
                      std::optional<Nonnull<Block*>> body)
                      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.
   // Use `Create()` instead. This is public only so Arena::New() can call it.
   FunctionDeclaration(SourceLocation source_loc, std::string name,
   FunctionDeclaration(SourceLocation source_loc, std::string name,
                       std::vector<Nonnull<GenericBinding*>> deduced_params,
                       std::vector<Nonnull<GenericBinding*>> deduced_params,
-                      std::optional<Nonnull<BindingPattern*>> me_pattern,
+                      std::optional<Nonnull<Pattern*>> me_pattern,
                       Nonnull<TuplePattern*> param_pattern,
                       Nonnull<TuplePattern*> param_pattern,
                       ReturnTerm return_term,
                       ReturnTerm return_term,
                       std::optional<Nonnull<Block*>> body)
                       std::optional<Nonnull<Block*>> body)
@@ -139,8 +139,8 @@ class FunctionDeclaration : public Declaration {
   auto deduced_parameters() -> llvm::ArrayRef<Nonnull<GenericBinding*>> {
   auto deduced_parameters() -> llvm::ArrayRef<Nonnull<GenericBinding*>> {
     return deduced_parameters_;
     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() const -> const TuplePattern& { return *param_pattern_; }
   auto param_pattern() -> TuplePattern& { return *param_pattern_; }
   auto param_pattern() -> TuplePattern& { return *param_pattern_; }
   auto return_term() const -> const ReturnTerm& { return return_term_; }
   auto return_term() const -> const ReturnTerm& { return return_term_; }
@@ -155,7 +155,7 @@ class FunctionDeclaration : public Declaration {
  private:
  private:
   std::string name_;
   std::string name_;
   std::vector<Nonnull<GenericBinding*>> deduced_parameters_;
   std::vector<Nonnull<GenericBinding*>> deduced_parameters_;
-  std::optional<Nonnull<BindingPattern*>> me_pattern_;
+  std::optional<Nonnull<Pattern*>> me_pattern_;
   Nonnull<TuplePattern*> param_pattern_;
   Nonnull<TuplePattern*> param_pattern_;
   ReturnTerm return_term_;
   ReturnTerm return_term_;
   std::optional<Nonnull<Block*>> body_;
   std::optional<Nonnull<Block*>> body_;

+ 9 - 0
explorer/ast/expression.h

@@ -168,6 +168,14 @@ class SimpleMemberAccessExpression : public Expression {
   auto object() const -> const Expression& { return *object_; }
   auto object() const -> const Expression& { return *object_; }
   auto object() -> Expression& { return *object_; }
   auto object() -> Expression& { return *object_; }
   auto member() const -> const std::string& { return member_; }
   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
   // If `object` has a generic type, returns the `ImplBinding` that
   // identifies its witness table. Otherwise, returns `std::nullopt`. Should not
   // identifies its witness table. Otherwise, returns `std::nullopt`. Should not
@@ -186,6 +194,7 @@ class SimpleMemberAccessExpression : public Expression {
   Nonnull<Expression*> object_;
   Nonnull<Expression*> object_;
   std::string member_;
   std::string member_;
   std::optional<Nonnull<const ImplBinding*>> impl_;
   std::optional<Nonnull<const ImplBinding*>> impl_;
+  bool is_field_addr_me_method_ = false;
 };
 };
 
 
 // A compound member access expression of the form `object.(path)`.
 // A compound member access expression of the form `object.(path)`.

+ 8 - 0
explorer/ast/pattern.cpp

@@ -56,6 +56,9 @@ void Pattern::Print(llvm::raw_ostream& out) const {
     case PatternKind::VarPattern:
     case PatternKind::VarPattern:
       out << "var" << cast<VarPattern>(*this).pattern();
       out << "var" << cast<VarPattern>(*this).pattern();
       break;
       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:
     case PatternKind::VarPattern:
       out << "var ...";
       out << "var ...";
       break;
       break;
+    case PatternKind::AddrPattern:
+      out << "addr ...";
+      break;
     case PatternKind::ExpressionPattern:
     case PatternKind::ExpressionPattern:
       out << "...";
       out << "...";
       break;
       break;
@@ -112,6 +118,8 @@ auto VisitNestedPatterns(const Pattern& pattern,
                                  visitor);
                                  visitor);
     case PatternKind::VarPattern:
     case PatternKind::VarPattern:
       return VisitNestedPatterns(cast<VarPattern>(pattern).pattern(), visitor);
       return VisitNestedPatterns(cast<VarPattern>(pattern).pattern(), visitor);
+    case PatternKind::AddrPattern:
+      return VisitNestedPatterns(cast<AddrPattern>(pattern).binding(), visitor);
     case PatternKind::BindingPattern:
     case PatternKind::BindingPattern:
     case PatternKind::AutoPattern:
     case PatternKind::AutoPattern:
     case PatternKind::ExpressionPattern:
     case PatternKind::ExpressionPattern:

+ 17 - 0
explorer/ast/pattern.h

@@ -184,6 +184,23 @@ class BindingPattern : public Pattern {
   std::optional<ValueCategory> value_category_;
   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.
 // A pattern that matches a tuple value field-wise.
 class TuplePattern : public Pattern {
 class TuplePattern : public Pattern {
  public:
  public:

+ 21 - 2
explorer/fuzzing/ast_to_proto.cpp

@@ -322,6 +322,10 @@ static auto PatternToProto(const Pattern& pattern) -> Fuzzing::Pattern {
       *pattern_proto.mutable_var_pattern()->mutable_pattern() =
       *pattern_proto.mutable_var_pattern()->mutable_pattern() =
           PatternToProto(cast<VarPattern>(pattern).pattern());
           PatternToProto(cast<VarPattern>(pattern).pattern());
       break;
       break;
+    case PatternKind::AddrPattern:
+      *pattern_proto.mutable_addr_pattern()->mutable_binding_pattern() =
+          BindingPatternToProto(cast<AddrPattern>(pattern).binding());
+      break;
   }
   }
   return pattern_proto;
   return pattern_proto;
 }
 }
@@ -479,8 +483,23 @@ static auto DeclarationToProto(const Declaration& declaration)
             GenericBindingToProto(*binding);
             GenericBindingToProto(*binding);
       }
       }
       if (function.is_method()) {
       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() =
       *function_proto->mutable_param_pattern() =
           TuplePatternToProto(function.param_pattern());
           TuplePatternToProto(function.param_pattern());

+ 32 - 12
explorer/fuzzing/fuzzer_corpus/886a1cbc0a58fed099ca0dc0d9da01ff9c0d0a75.textproto → explorer/fuzzing/fuzzer_corpus/017a765e283355ded618ed95de5da4e3f2dd4b52.textproto

@@ -10,12 +10,14 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           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 {
         function {
           name: "Mul"
           name: "Mul"
           me_pattern {
           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 {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -122,6 +127,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -172,6 +178,7 @@ compilation_unit {
         function {
         function {
           name: "Mul"
           name: "Mul"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -181,6 +188,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -284,6 +292,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -294,6 +303,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -325,6 +335,7 @@ compilation_unit {
         function {
         function {
           name: "Scale"
           name: "Scale"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -335,6 +346,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -366,6 +378,7 @@ compilation_unit {
         function {
         function {
           name: "Hold"
           name: "Hold"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -376,6 +389,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -528,6 +542,7 @@ compilation_unit {
             function {
             function {
               name: "Add"
               name: "Add"
               me_pattern {
               me_pattern {
+                binding_pattern {
                 name: "me"
                 name: "me"
                 type {
                 type {
                   expression_pattern {
                   expression_pattern {
@@ -538,6 +553,7 @@ compilation_unit {
                     }
                     }
                   }
                   }
                 }
                 }
+                }
               }
               }
               param_pattern {
               param_pattern {
                 fields {
                 fields {
@@ -635,6 +651,7 @@ compilation_unit {
             function {
             function {
               name: "Scale"
               name: "Scale"
               me_pattern {
               me_pattern {
+                binding_pattern {
                 name: "me"
                 name: "me"
                 type {
                 type {
                   expression_pattern {
                   expression_pattern {
@@ -645,6 +662,7 @@ compilation_unit {
                     }
                     }
                   }
                   }
                 }
                 }
+                }
               }
               }
               param_pattern {
               param_pattern {
                 fields {
                 fields {
@@ -731,6 +749,7 @@ compilation_unit {
             function {
             function {
               name: "Hold"
               name: "Hold"
               me_pattern {
               me_pattern {
+                binding_pattern {
                 name: "me"
                 name: "me"
                 type {
                 type {
                   expression_pattern {
                   expression_pattern {
@@ -741,6 +760,7 @@ compilation_unit {
                     }
                     }
                   }
                   }
                 }
                 }
+                }
               }
               }
               param_pattern {
               param_pattern {
                 fields {
                 fields {

+ 8 - 0
explorer/fuzzing/fuzzer_corpus/93dcb9eeaeeff3b36f8201ae4f1ad5893bb39aa8.textproto → explorer/fuzzing/fuzzer_corpus/0ee3d72e3cab1b0907f04f35b2d33fb946ab32c9.textproto

@@ -25,6 +25,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -35,6 +36,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -66,6 +68,7 @@ compilation_unit {
         function {
         function {
           name: "Scale"
           name: "Scale"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -76,6 +79,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -241,6 +245,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -263,6 +268,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -384,6 +390,7 @@ compilation_unit {
         function {
         function {
           name: "Scale"
           name: "Scale"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -406,6 +413,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {

+ 8 - 0
explorer/fuzzing/fuzzer_corpus/d27c6d16e838d3a2fb3e829f92718ea93271d45a.textproto → explorer/fuzzing/fuzzer_corpus/1844089b39db6518836420fcb6a5d37b3e99424f.textproto

@@ -10,6 +10,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -20,6 +21,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -51,6 +53,7 @@ compilation_unit {
         function {
         function {
           name: "Scale"
           name: "Scale"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -61,6 +64,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -146,6 +150,7 @@ compilation_unit {
             function {
             function {
               name: "Add"
               name: "Add"
               me_pattern {
               me_pattern {
+                binding_pattern {
                 name: "me"
                 name: "me"
                 type {
                 type {
                   expression_pattern {
                   expression_pattern {
@@ -156,6 +161,7 @@ compilation_unit {
                     }
                     }
                   }
                   }
                 }
                 }
+                }
               }
               }
               param_pattern {
               param_pattern {
                 fields {
                 fields {
@@ -253,6 +259,7 @@ compilation_unit {
             function {
             function {
               name: "Scale"
               name: "Scale"
               me_pattern {
               me_pattern {
+                binding_pattern {
                 name: "me"
                 name: "me"
                 type {
                 type {
                   expression_pattern {
                   expression_pattern {
@@ -263,6 +270,7 @@ compilation_unit {
                     }
                     }
                   }
                   }
                 }
                 }
+                }
               }
               }
               param_pattern {
               param_pattern {
                 fields {
                 fields {

+ 4 - 0
explorer/fuzzing/fuzzer_corpus/a8047c2f828519a1384aade7624c73d912acd0a0.textproto → explorer/fuzzing/fuzzer_corpus/2caf42dcf02bff184fa653bf36054b9d83704e30.textproto

@@ -10,6 +10,7 @@ compilation_unit {
         function {
         function {
           name: "Op"
           name: "Op"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -20,6 +21,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -121,6 +123,7 @@ compilation_unit {
         function {
         function {
           name: "Op"
           name: "Op"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -131,6 +134,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {

+ 6 - 0
explorer/fuzzing/fuzzer_corpus/3dc8675eb42820ac93e26afbc4af62d157382861.textproto → explorer/fuzzing/fuzzer_corpus/32e0eb929035d7c53b3d8566ac48ef0c3b82b32e.textproto

@@ -25,6 +25,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -35,6 +36,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -161,6 +163,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -170,6 +173,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -315,6 +319,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -325,6 +330,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {

+ 8 - 0
explorer/fuzzing/fuzzer_corpus/cc5f0c26bf337000aa697c93880d18f0d9668b13.textproto → explorer/fuzzing/fuzzer_corpus/5357de7edef4e3bff993192d9538493ae80f5fa8.textproto

@@ -25,6 +25,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -35,6 +36,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -158,6 +160,7 @@ compilation_unit {
         function {
         function {
           name: "Clone"
           name: "Clone"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -181,6 +184,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
           }
           }
@@ -247,6 +251,7 @@ compilation_unit {
         function {
         function {
           name: "SumXY"
           name: "SumXY"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -270,6 +275,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
           }
           }
@@ -409,6 +415,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -418,6 +425,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {

+ 8 - 0
explorer/fuzzing/fuzzer_corpus/79551d0f40545d4aa5e988baa9ec1e946f91e601.textproto → explorer/fuzzing/fuzzer_corpus/5e4bce73c210e45269126773f257d95d4d269072.textproto

@@ -10,6 +10,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -20,6 +21,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -51,6 +53,7 @@ compilation_unit {
         function {
         function {
           name: "Scale"
           name: "Scale"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -61,6 +64,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -148,6 +152,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -158,6 +163,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -255,6 +261,7 @@ compilation_unit {
         function {
         function {
           name: "Scale"
           name: "Scale"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -265,6 +272,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {

+ 2 - 0
explorer/fuzzing/fuzzer_corpus/e4cdfa4f32f0adc18ed39f6a9a483835db596ee5.textproto → explorer/fuzzing/fuzzer_corpus/63979179f0b4279dbf7a98a3a7b9837393d43e8a.textproto

@@ -65,6 +65,7 @@ compilation_unit {
         function {
         function {
           name: "GetX"
           name: "GetX"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -75,6 +76,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
           }
           }

+ 12 - 0
explorer/fuzzing/fuzzer_corpus/f0c1f0eaa05127e95e5d9b167051b84b2fa54359.textproto → explorer/fuzzing/fuzzer_corpus/6c86299b17c54466628587a48c2ec0e9d3029fc7.textproto

@@ -10,6 +10,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -20,6 +21,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -51,6 +53,7 @@ compilation_unit {
         function {
         function {
           name: "Scale"
           name: "Scale"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -61,6 +64,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -146,6 +150,7 @@ compilation_unit {
             function {
             function {
               name: "Add"
               name: "Add"
               me_pattern {
               me_pattern {
+                binding_pattern {
                 name: "me"
                 name: "me"
                 type {
                 type {
                   expression_pattern {
                   expression_pattern {
@@ -156,6 +161,7 @@ compilation_unit {
                     }
                     }
                   }
                   }
                 }
                 }
+                }
               }
               }
               param_pattern {
               param_pattern {
                 fields {
                 fields {
@@ -253,6 +259,7 @@ compilation_unit {
             function {
             function {
               name: "Scale"
               name: "Scale"
               me_pattern {
               me_pattern {
+                binding_pattern {
                 name: "me"
                 name: "me"
                 type {
                 type {
                   expression_pattern {
                   expression_pattern {
@@ -263,6 +270,7 @@ compilation_unit {
                     }
                     }
                   }
                   }
                 }
                 }
+                }
               }
               }
               param_pattern {
               param_pattern {
                 fields {
                 fields {
@@ -399,6 +407,7 @@ compilation_unit {
             function {
             function {
               name: "Add"
               name: "Add"
               me_pattern {
               me_pattern {
+                binding_pattern {
                 name: "me"
                 name: "me"
                 type {
                 type {
                   expression_pattern {
                   expression_pattern {
@@ -409,6 +418,7 @@ compilation_unit {
                     }
                     }
                   }
                   }
                 }
                 }
+                }
               }
               }
               param_pattern {
               param_pattern {
                 fields {
                 fields {
@@ -526,6 +536,7 @@ compilation_unit {
             function {
             function {
               name: "Scale"
               name: "Scale"
               me_pattern {
               me_pattern {
+                binding_pattern {
                 name: "me"
                 name: "me"
                 type {
                 type {
                   expression_pattern {
                   expression_pattern {
@@ -536,6 +547,7 @@ compilation_unit {
                     }
                     }
                   }
                   }
                 }
                 }
+                }
               }
               }
               param_pattern {
               param_pattern {
                 fields {
                 fields {

+ 8 - 0
explorer/fuzzing/fuzzer_corpus/d6f13d6e870f2cde1ac1985bd386bbb22ec19f1a.textproto → explorer/fuzzing/fuzzer_corpus/6f589265e1e503d2e01043d6a332026d1693095e.textproto

@@ -25,6 +25,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -35,6 +36,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -66,6 +68,7 @@ compilation_unit {
         function {
         function {
           name: "Scale"
           name: "Scale"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -76,6 +79,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -202,6 +206,7 @@ compilation_unit {
             function {
             function {
               name: "Add"
               name: "Add"
               me_pattern {
               me_pattern {
+                binding_pattern {
                 name: "me"
                 name: "me"
                 type {
                 type {
                   expression_pattern {
                   expression_pattern {
@@ -212,6 +217,7 @@ compilation_unit {
                     }
                     }
                   }
                   }
                 }
                 }
+                }
               }
               }
               param_pattern {
               param_pattern {
                 fields {
                 fields {
@@ -309,6 +315,7 @@ compilation_unit {
             function {
             function {
               name: "Scale"
               name: "Scale"
               me_pattern {
               me_pattern {
+                binding_pattern {
                 name: "me"
                 name: "me"
                 type {
                 type {
                   expression_pattern {
                   expression_pattern {
@@ -319,6 +326,7 @@ compilation_unit {
                     }
                     }
                   }
                   }
                 }
                 }
+                }
               }
               }
               param_pattern {
               param_pattern {
                 fields {
                 fields {

+ 4 - 0
explorer/fuzzing/fuzzer_corpus/53c90be68e61d528ae738d538007572079edecfb.textproto → explorer/fuzzing/fuzzer_corpus/72624c04b293dcee7ecc0129b6e196195ca84332.textproto

@@ -25,6 +25,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -35,6 +36,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -241,6 +243,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -250,6 +253,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {

+ 8 - 0
explorer/fuzzing/fuzzer_corpus/f0791c1c35ad07c87e3b12ad58bdfd3757fa7397.textproto → explorer/fuzzing/fuzzer_corpus/7b7e24319e8f63e6c3e99f8cbc81da7e9e47390a.textproto

@@ -25,6 +25,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -35,6 +36,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -66,6 +68,7 @@ compilation_unit {
         function {
         function {
           name: "Scale"
           name: "Scale"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -76,6 +79,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -202,6 +206,7 @@ compilation_unit {
             function {
             function {
               name: "Add"
               name: "Add"
               me_pattern {
               me_pattern {
+                binding_pattern {
                 name: "me"
                 name: "me"
                 type {
                 type {
                   expression_pattern {
                   expression_pattern {
@@ -212,6 +217,7 @@ compilation_unit {
                     }
                     }
                   }
                   }
                 }
                 }
+                }
               }
               }
               param_pattern {
               param_pattern {
                 fields {
                 fields {
@@ -309,6 +315,7 @@ compilation_unit {
             function {
             function {
               name: "Scale"
               name: "Scale"
               me_pattern {
               me_pattern {
+                binding_pattern {
                 name: "me"
                 name: "me"
                 type {
                 type {
                   expression_pattern {
                   expression_pattern {
@@ -319,6 +326,7 @@ compilation_unit {
                     }
                     }
                   }
                   }
                 }
                 }
+                }
               }
               }
               param_pattern {
               param_pattern {
                 fields {
                 fields {

+ 8 - 0
explorer/fuzzing/fuzzer_corpus/defec684307f53851236f5f0cd91353e44b522e8.textproto → explorer/fuzzing/fuzzer_corpus/81b5d416277f5b28d98ac9b175f73389d9857655.textproto

@@ -25,6 +25,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -35,6 +36,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -66,6 +68,7 @@ compilation_unit {
         function {
         function {
           name: "Scale"
           name: "Scale"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -76,6 +79,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -229,6 +233,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -239,6 +244,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -336,6 +342,7 @@ compilation_unit {
         function {
         function {
           name: "Scale"
           name: "Scale"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -346,6 +353,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {

+ 8 - 0
explorer/fuzzing/fuzzer_corpus/f2f794705121fc76bfb94de7a7507becbc6ad10a.textproto → explorer/fuzzing/fuzzer_corpus/8fa92df904a230ee4b0ecf1362170a2551aec98b.textproto

@@ -25,6 +25,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -35,6 +36,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -66,6 +68,7 @@ compilation_unit {
         function {
         function {
           name: "Scale"
           name: "Scale"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -76,6 +79,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -202,6 +206,7 @@ compilation_unit {
             function {
             function {
               name: "Add"
               name: "Add"
               me_pattern {
               me_pattern {
+                binding_pattern {
                 name: "me"
                 name: "me"
                 type {
                 type {
                   expression_pattern {
                   expression_pattern {
@@ -212,6 +217,7 @@ compilation_unit {
                     }
                     }
                   }
                   }
                 }
                 }
+                }
               }
               }
               param_pattern {
               param_pattern {
                 fields {
                 fields {
@@ -309,6 +315,7 @@ compilation_unit {
             function {
             function {
               name: "Scale"
               name: "Scale"
               me_pattern {
               me_pattern {
+                binding_pattern {
                 name: "me"
                 name: "me"
                 type {
                 type {
                   expression_pattern {
                   expression_pattern {
@@ -319,6 +326,7 @@ compilation_unit {
                     }
                     }
                   }
                   }
                 }
                 }
+                }
               }
               }
               param_pattern {
               param_pattern {
                 fields {
                 fields {

+ 6 - 0
explorer/fuzzing/fuzzer_corpus/6d89c0f37960217a1aed0d102cb41057306ba2ad.textproto → explorer/fuzzing/fuzzer_corpus/9a79849f37e616453382dcd0ff273c080d3b4f7f.textproto

@@ -25,6 +25,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -35,6 +36,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -161,6 +163,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -170,6 +173,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -328,6 +332,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -351,6 +356,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {

+ 8 - 0
explorer/fuzzing/fuzzer_corpus/605b1f6a1f0b6806f5da052014a56403a3691024.textproto → explorer/fuzzing/fuzzer_corpus/9bb0b055035cb4965aa9432c34bdb1be0f8c3b80.textproto

@@ -10,6 +10,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -20,6 +21,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -51,6 +53,7 @@ compilation_unit {
         function {
         function {
           name: "Scale"
           name: "Scale"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -61,6 +64,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -146,6 +150,7 @@ compilation_unit {
             function {
             function {
               name: "Add"
               name: "Add"
               me_pattern {
               me_pattern {
+                binding_pattern {
                 name: "me"
                 name: "me"
                 type {
                 type {
                   expression_pattern {
                   expression_pattern {
@@ -156,6 +161,7 @@ compilation_unit {
                     }
                     }
                   }
                   }
                 }
                 }
+                }
               }
               }
               param_pattern {
               param_pattern {
                 fields {
                 fields {
@@ -253,6 +259,7 @@ compilation_unit {
             function {
             function {
               name: "Scale"
               name: "Scale"
               me_pattern {
               me_pattern {
+                binding_pattern {
                 name: "me"
                 name: "me"
                 type {
                 type {
                   expression_pattern {
                   expression_pattern {
@@ -263,6 +270,7 @@ compilation_unit {
                     }
                     }
                   }
                   }
                 }
                 }
+                }
               }
               }
               param_pattern {
               param_pattern {
                 fields {
                 fields {

+ 4 - 0
explorer/fuzzing/fuzzer_corpus/bade121153d00cc778f13538192f224f6d215d55.textproto → explorer/fuzzing/fuzzer_corpus/a04fd176eb32a1a2500bf298f4f5deb37b9fa406.textproto

@@ -25,6 +25,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -35,6 +36,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -390,6 +392,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -399,6 +402,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {

+ 8 - 6
explorer/fuzzing/fuzzer_corpus/dc02f2222475e43c33fb8d9713ade9cc67f52edc.textproto → explorer/fuzzing/fuzzer_corpus/a88508d94032d0429d1cba11c1df90deb142c155.textproto

@@ -51,12 +51,14 @@ compilation_unit {
         function {
         function {
           name: "GetX"
           name: "GetX"
           me_pattern {
           me_pattern {
-            name: "me"
-            type {
-              expression_pattern {
-                expression {
-                  identifier {
-                    name: "Point"
+            binding_pattern {
+              name: "me"
+              type {
+                expression_pattern {
+                  expression {
+                    identifier {
+                      name: "Point"
+                    }
                   }
                   }
                 }
                 }
               }
               }

+ 8 - 0
explorer/fuzzing/fuzzer_corpus/d76dbdfb3092a4e7d4368223e4b4d7208a4d2805.textproto → explorer/fuzzing/fuzzer_corpus/d44b1b3f6ff018d0829e0d73f551d0144b39e638.textproto

@@ -10,6 +10,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -20,6 +21,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -51,6 +53,7 @@ compilation_unit {
         function {
         function {
           name: "Scale"
           name: "Scale"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -61,6 +64,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -148,6 +152,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -158,6 +163,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -255,6 +261,7 @@ compilation_unit {
         function {
         function {
           name: "Scale"
           name: "Scale"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -265,6 +272,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {

+ 6 - 0
explorer/fuzzing/fuzzer_corpus/854bb3af6f9f1f6a0e31a7103720864316abf3bc.textproto → explorer/fuzzing/fuzzer_corpus/f0249ef671686916199dbce1467d741102a68717.textproto

@@ -25,6 +25,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -35,6 +36,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -161,6 +163,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -170,6 +173,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -328,6 +332,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -351,6 +356,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {

+ 8 - 0
explorer/fuzzing/fuzzer_corpus/dba92dce40512177d3bf143b088da7eccc8fa214.textproto → explorer/fuzzing/fuzzer_corpus/f986b7976441ebd0928d8f4d13c6ff2be6a05f50.textproto

@@ -10,6 +10,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -20,6 +21,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -51,6 +53,7 @@ compilation_unit {
         function {
         function {
           name: "Scale"
           name: "Scale"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -61,6 +64,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -146,6 +150,7 @@ compilation_unit {
             function {
             function {
               name: "Add"
               name: "Add"
               me_pattern {
               me_pattern {
+                binding_pattern {
                 name: "me"
                 name: "me"
                 type {
                 type {
                   expression_pattern {
                   expression_pattern {
@@ -156,6 +161,7 @@ compilation_unit {
                     }
                     }
                   }
                   }
                 }
                 }
+                }
               }
               }
               param_pattern {
               param_pattern {
                 fields {
                 fields {
@@ -253,6 +259,7 @@ compilation_unit {
             function {
             function {
               name: "Scale"
               name: "Scale"
               me_pattern {
               me_pattern {
+                binding_pattern {
                 name: "me"
                 name: "me"
                 type {
                 type {
                   expression_pattern {
                   expression_pattern {
@@ -263,6 +270,7 @@ compilation_unit {
                     }
                     }
                   }
                   }
                 }
                 }
+                }
               }
               }
               param_pattern {
               param_pattern {
                 fields {
                 fields {

+ 2 - 0
explorer/fuzzing/fuzzer_corpus/ea5f89368e963868e6ff283238f3d2811e828b2f.textproto → explorer/fuzzing/fuzzer_corpus/fc5f5e4f348579cedbecae8dccafc9f9dae68237.textproto

@@ -78,6 +78,7 @@ compilation_unit {
         function {
         function {
           name: "GetX"
           name: "GetX"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -101,6 +102,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
           }
           }

+ 4 - 0
explorer/fuzzing/fuzzer_corpus/da3113c74912fae50b4d30bf6351ad30985b4695.textproto → explorer/fuzzing/fuzzer_corpus/fda984fd483f47ca29fd55b54173f77ef690b4ee.textproto

@@ -25,6 +25,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -35,6 +36,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -451,6 +453,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -460,6 +463,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {

+ 8 - 0
explorer/fuzzing/fuzzer_corpus/5ae7e1ab2593f54e01e0f1f2b9cacc06701c17a8.textproto → explorer/fuzzing/fuzzer_corpus/fe3c5db046e0dae74603f2c43ed1af68eea9a6ae.textproto

@@ -25,6 +25,7 @@ compilation_unit {
         function {
         function {
           name: "Add"
           name: "Add"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -35,6 +36,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -66,6 +68,7 @@ compilation_unit {
         function {
         function {
           name: "Scale"
           name: "Scale"
           me_pattern {
           me_pattern {
+            binding_pattern {
             name: "me"
             name: "me"
             type {
             type {
               expression_pattern {
               expression_pattern {
@@ -76,6 +79,7 @@ compilation_unit {
                 }
                 }
               }
               }
             }
             }
+            }
           }
           }
           param_pattern {
           param_pattern {
             fields {
             fields {
@@ -215,6 +219,7 @@ compilation_unit {
             function {
             function {
               name: "Add"
               name: "Add"
               me_pattern {
               me_pattern {
+                binding_pattern {
                 name: "me"
                 name: "me"
                 type {
                 type {
                   expression_pattern {
                   expression_pattern {
@@ -225,6 +230,7 @@ compilation_unit {
                     }
                     }
                   }
                   }
                 }
                 }
+                }
               }
               }
               param_pattern {
               param_pattern {
                 fields {
                 fields {
@@ -322,6 +328,7 @@ compilation_unit {
             function {
             function {
               name: "Scale"
               name: "Scale"
               me_pattern {
               me_pattern {
+                binding_pattern {
                 name: "me"
                 name: "me"
                 type {
                 type {
                   expression_pattern {
                   expression_pattern {
@@ -332,6 +339,7 @@ compilation_unit {
                     }
                     }
                   }
                   }
                 }
                 }
+                }
               }
               }
               param_pattern {
               param_pattern {
                 fields {
                 fields {

+ 2 - 2
explorer/interpreter/heap.cpp

@@ -24,8 +24,8 @@ auto Heap::AllocateValue(Nonnull<const Value*> v) -> AllocationId {
 auto Heap::Read(const Address& a, SourceLocation source_loc) const
 auto Heap::Read(const Address& a, SourceLocation source_loc) const
     -> ErrorOr<Nonnull<const Value*>> {
     -> ErrorOr<Nonnull<const Value*>> {
   CARBON_RETURN_IF_ERROR(this->CheckAlive(a.allocation_, source_loc));
   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,
 auto Heap::Write(const Address& a, Nonnull<const Value*> v,

+ 58 - 23
explorer/interpreter/interpreter.cpp

@@ -209,8 +209,8 @@ auto PatternMatch(Nonnull<const Value*> p, Nonnull<const Value*> v,
                   SourceLocation source_loc,
                   SourceLocation source_loc,
                   std::optional<Nonnull<RuntimeScope*>> bindings,
                   std::optional<Nonnull<RuntimeScope*>> bindings,
                   BindingMap& generic_args,
                   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) {
   if (trace_stream) {
     **trace_stream << "match pattern " << *p << "\nwith value " << *v << "\n";
     **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;
       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: {
     case Value::Kind::VariableType: {
       const auto& var_type = cast<VariableType>(*p);
       const auto& var_type = cast<VariableType>(*p);
       generic_args[&var_type.binding()] = v;
       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());
           CARBON_CHECK(p_tup.elements().size() == v_tup.elements().size());
           for (size_t i = 0; i < p_tup.elements().size(); ++i) {
           for (size_t i = 0; i < p_tup.elements().size(); ++i) {
             if (!PatternMatch(p_tup.elements()[i], v_tup.elements()[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;
               return false;
             }
             }
           }  // for
           }  // for
@@ -255,7 +263,7 @@ auto PatternMatch(Nonnull<const Value*> p, Nonnull<const Value*> v,
                      v_struct.elements()[i].name);
                      v_struct.elements()[i].name);
         if (!PatternMatch(p_struct.elements()[i].value,
         if (!PatternMatch(p_struct.elements()[i].value,
                           v_struct.elements()[i].value, source_loc, bindings,
                           v_struct.elements()[i].value, source_loc, bindings,
-                          generic_args, trace_stream)) {
+                          generic_args, trace_stream, arena)) {
           return false;
           return false;
         }
         }
       }
       }
@@ -271,7 +279,7 @@ auto PatternMatch(Nonnull<const Value*> p, Nonnull<const Value*> v,
             return false;
             return false;
           }
           }
           return PatternMatch(&p_alt.argument(), &v_alt.argument(), source_loc,
           return PatternMatch(&p_alt.argument(), &v_alt.argument(), source_loc,
-                              bindings, generic_args, trace_stream);
+                              bindings, generic_args, trace_stream, arena);
         }
         }
         default:
         default:
           CARBON_FATAL() << "expected a choice alternative in pattern, not "
           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& p_fn = cast<FunctionType>(*p);
           const auto& v_fn = cast<FunctionType>(*v);
           const auto& v_fn = cast<FunctionType>(*v);
           if (!PatternMatch(&p_fn.parameters(), &v_fn.parameters(), source_loc,
           if (!PatternMatch(&p_fn.parameters(), &v_fn.parameters(), source_loc,
-                            bindings, generic_args, trace_stream)) {
+                            bindings, generic_args, trace_stream, arena)) {
             return false;
             return false;
           }
           }
           if (!PatternMatch(&p_fn.return_type(), &v_fn.return_type(),
           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 false;
           }
           }
           return true;
           return true;
@@ -503,6 +512,7 @@ auto Interpreter::Convert(Nonnull<const Value*> value,
     case Value::Kind::ContinuationType:
     case Value::Kind::ContinuationType:
     case Value::Kind::VariableType:
     case Value::Kind::VariableType:
     case Value::Kind::BindingPlaceholderValue:
     case Value::Kind::BindingPlaceholderValue:
+    case Value::Kind::AddrValue:
     case Value::Kind::AlternativeConstructorValue:
     case Value::Kind::AlternativeConstructorValue:
     case Value::Kind::ContinuationValue:
     case Value::Kind::ContinuationValue:
     case Value::Kind::StringType:
     case Value::Kind::StringType:
@@ -637,9 +647,9 @@ auto Interpreter::CallFunction(const CallExpression& call,
 
 
       RuntimeScope function_scope(&heap_);
       RuntimeScope function_scope(&heap_);
       BindingMap generic_args;
       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())
       CARBON_CHECK(function.body().has_value())
           << "Calling a function that's missing a body";
           << "Calling a function that's missing a body";
       return todo_.Spawn(std::make_unique<StatementAction>(*function.body()),
       return todo_.Spawn(std::make_unique<StatementAction>(*function.body()),
@@ -657,10 +667,10 @@ auto Interpreter::CallFunction(const CallExpression& call,
       BindingMap generic_args;
       BindingMap generic_args;
       CARBON_CHECK(PatternMatch(&method.me_pattern().value(), m.receiver(),
       CARBON_CHECK(PatternMatch(&method.me_pattern().value(), m.receiver(),
                                 call.source_loc(), &method_scope, generic_args,
                                 call.source_loc(), &method_scope, generic_args,
-                                trace_stream_));
+                                trace_stream_, this->arena_));
       CARBON_CHECK(PatternMatch(&method.param_pattern().value(), converted_args,
       CARBON_CHECK(PatternMatch(&method.param_pattern().value(), converted_args,
                                 call.source_loc(), &method_scope, generic_args,
                                 call.source_loc(), &method_scope, generic_args,
-                                trace_stream_));
+                                trace_stream_, this->arena_));
       // Bring the class type arguments into scope.
       // Bring the class type arguments into scope.
       for (const auto& [bind, val] : m.type_args()) {
       for (const auto& [bind, val] : m.type_args()) {
         method_scope.Initialize(bind, val);
         method_scope.Initialize(bind, val);
@@ -681,7 +691,8 @@ auto Interpreter::CallFunction(const CallExpression& call,
       RuntimeScope params_scope(&heap_);
       RuntimeScope params_scope(&heap_);
       BindingMap generic_args;
       BindingMap generic_args;
       CARBON_CHECK(PatternMatch(&name.params().value(), arg, call.source_loc(),
       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()) {
       switch (decl.kind()) {
         case DeclarationKind::ClassDeclaration: {
         case DeclarationKind::ClassDeclaration: {
           switch (phase()) {
           switch (phase()) {
@@ -804,9 +815,17 @@ auto Interpreter::StepExp() -> ErrorOr<Success> {
     case ExpressionKind::SimpleMemberAccessExpression: {
     case ExpressionKind::SimpleMemberAccessExpression: {
       const auto& access = cast<SimpleMemberAccessExpression>(exp);
       const auto& access = cast<SimpleMemberAccessExpression>(exp);
       if (act.pos() == 0) {
       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 {
       } else {
+        //    { { v :: [].f :: C, E, F} :: S, H}
+        // -> { { v_f :: C, E, F} : S, H}
         if (const auto* member_name_type =
         if (const auto* member_name_type =
                 dyn_cast<TypeOfMemberName>(&access.static_type())) {
                 dyn_cast<TypeOfMemberName>(&access.static_type())) {
           // The result is a member name, such as in `Type.field_name`. Form a
           // 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);
             witness = cast<Witness>(witness_value);
           }
           }
           FieldPath::Component member(access.member(), witness);
           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(
           CARBON_ASSIGN_OR_RETURN(
               Nonnull<const Value*> member_value,
               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);
           return todo_.FinishAction(member_value);
         }
         }
       }
       }
@@ -892,9 +919,9 @@ auto Interpreter::StepExp() -> ErrorOr<Success> {
                                 exp.source_loc()));
                                 exp.source_loc()));
           }
           }
           FieldPath::Component field(access.member().name(), witness);
           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);
           return todo_.FinishAction(member);
         }
         }
       }
       }
@@ -1148,6 +1175,14 @@ auto Interpreter::StepPattern() -> ErrorOr<Success> {
       } else {
       } else {
         return todo_.FinishAction(act.results()[0]);
         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(),
             Convert(act.results()[0], &c.pattern().static_type(),
                     stmt.source_loc()));
                     stmt.source_loc()));
         if (PatternMatch(&c.pattern().value(), val, stmt.source_loc(), &matches,
         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.
           // Ensure we don't process any more clauses.
           act.set_pos(match_stmt.clauses().size() + 1);
           act.set_pos(match_stmt.clauses().size() + 1);
           todo_.MergeScope(std::move(matches));
           todo_.MergeScope(std::move(matches));
@@ -1262,7 +1297,7 @@ auto Interpreter::StepStmt() -> ErrorOr<Success> {
         RuntimeScope matches(&heap_);
         RuntimeScope matches(&heap_);
         BindingMap generic_args;
         BindingMap generic_args;
         CARBON_CHECK(PatternMatch(p, v, stmt.source_loc(), &matches,
         CARBON_CHECK(PatternMatch(p, v, stmt.source_loc(), &matches,
-                                  generic_args, trace_stream_))
+                                  generic_args, trace_stream_, this->arena_))
             << stmt.source_loc()
             << stmt.source_loc()
             << ": internal error in variable definition, match failed";
             << ": internal error in variable definition, match failed";
         todo_.MergeScope(std::move(matches));
         todo_.MergeScope(std::move(matches));

+ 2 - 1
explorer/interpreter/interpreter.h

@@ -53,7 +53,8 @@ auto InterpPattern(Nonnull<const Pattern*> p, Nonnull<Arena*> arena,
 [[nodiscard]] auto PatternMatch(
 [[nodiscard]] auto PatternMatch(
     Nonnull<const Value*> p, Nonnull<const Value*> v, SourceLocation source_loc,
     Nonnull<const Value*> p, Nonnull<const Value*> v, SourceLocation source_loc,
     std::optional<Nonnull<RuntimeScope*>> bindings, BindingMap& generic_args,
     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
 }  // namespace Carbon
 
 

+ 4 - 0
explorer/interpreter/resolve_names.cpp

@@ -242,6 +242,10 @@ static auto ResolveNames(Pattern& pattern, StaticScope& enclosing_scope)
       CARBON_RETURN_IF_ERROR(
       CARBON_RETURN_IF_ERROR(
           ResolveNames(cast<VarPattern>(pattern).pattern(), enclosing_scope));
           ResolveNames(cast<VarPattern>(pattern).pattern(), enclosing_scope));
       break;
       break;
+    case PatternKind::AddrPattern:
+      CARBON_RETURN_IF_ERROR(
+          ResolveNames(cast<AddrPattern>(pattern).binding(), enclosing_scope));
+      break;
   }
   }
   return Success();
   return Success();
 }
 }

+ 61 - 14
explorer/interpreter/type_checker.cpp

@@ -77,6 +77,7 @@ static auto IsTypeOfType(Nonnull<const Value*> value) -> bool {
     case Value::Kind::NominalClassValue:
     case Value::Kind::NominalClassValue:
     case Value::Kind::AlternativeValue:
     case Value::Kind::AlternativeValue:
     case Value::Kind::BindingPlaceholderValue:
     case Value::Kind::BindingPlaceholderValue:
+    case Value::Kind::AddrValue:
     case Value::Kind::AlternativeConstructorValue:
     case Value::Kind::AlternativeConstructorValue:
     case Value::Kind::ContinuationValue:
     case Value::Kind::ContinuationValue:
     case Value::Kind::StringValue:
     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::NominalClassValue:
     case Value::Kind::AlternativeValue:
     case Value::Kind::AlternativeValue:
     case Value::Kind::BindingPlaceholderValue:
     case Value::Kind::BindingPlaceholderValue:
+    case Value::Kind::AddrValue:
     case Value::Kind::AlternativeConstructorValue:
     case Value::Kind::AlternativeConstructorValue:
     case Value::Kind::ContinuationValue:
     case Value::Kind::ContinuationValue:
     case Value::Kind::StringValue:
     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::BoolType:
     case Value::Kind::TypeType:
     case Value::Kind::TypeType:
     case Value::Kind::FunctionType:
     case Value::Kind::FunctionType:
-    case Value::Kind::PointerType:
     case Value::Kind::StructType:
     case Value::Kind::StructType:
     case Value::Kind::NominalClassType:
     case Value::Kind::NominalClassType:
     case Value::Kind::InterfaceType:
     case Value::Kind::InterfaceType:
@@ -169,6 +170,9 @@ static auto IsType(Nonnull<const Value*> value, bool concrete = false) -> bool {
       }
       }
       return true;
       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) {
   if (has_arguments) {
     TupleValue args(interface.arguments);
     TupleValue args(interface.arguments);
     if (!PatternMatch(&iface_decl->params().value()->value(), &args, source_loc,
     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();
       return bad_builtin();
     }
     }
   }
   }
@@ -703,6 +707,7 @@ auto TypeChecker::ArgumentDeduction(
     case Value::Kind::NominalClassValue:
     case Value::Kind::NominalClassValue:
     case Value::Kind::AlternativeValue:
     case Value::Kind::AlternativeValue:
     case Value::Kind::BindingPlaceholderValue:
     case Value::Kind::BindingPlaceholderValue:
+    case Value::Kind::AddrValue:
     case Value::Kind::AlternativeConstructorValue:
     case Value::Kind::AlternativeConstructorValue:
     case Value::Kind::ContinuationValue:
     case Value::Kind::ContinuationValue:
     case Value::Kind::StringValue: {
     case Value::Kind::StringValue: {
@@ -814,6 +819,7 @@ auto TypeChecker::Substitute(
     case Value::Kind::NominalClassValue:
     case Value::Kind::NominalClassValue:
     case Value::Kind::AlternativeValue:
     case Value::Kind::AlternativeValue:
     case Value::Kind::BindingPlaceholderValue:
     case Value::Kind::BindingPlaceholderValue:
+    case Value::Kind::AddrValue:
     case Value::Kind::AlternativeConstructorValue:
     case Value::Kind::AlternativeConstructorValue:
     case Value::Kind::ContinuationValue:
     case Value::Kind::ContinuationValue:
     case Value::Kind::StringValue:
     case Value::Kind::StringValue:
@@ -1141,9 +1147,24 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
               case DeclarationKind::VariableDeclaration:
               case DeclarationKind::VariableDeclaration:
                 access.set_value_category(access.object().value_category());
                 access.set_value_category(access.object().value_category());
                 break;
                 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);
                 access.set_value_category(ValueCategory::Let);
                 break;
                 break;
+              }
               default:
               default:
                 CARBON_FATAL() << "member " << access.member()
                 CARBON_FATAL() << "member " << access.member()
                                << " is not a field or method";
                                << " is not a field or method";
@@ -1512,8 +1533,9 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
           op.set_value_category(ValueCategory::Var);
           op.set_value_category(ValueCategory::Var);
           return Success();
           return Success();
         case Operator::Ptr:
         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_static_type(arena_->New<TypeType>());
           op.set_value_category(ValueCategory::Let);
           op.set_value_category(ValueCategory::Let);
           return Success();
           return Success();
@@ -1805,7 +1827,8 @@ auto TypeChecker::TypeCheckPattern(
         } else {
         } else {
           BindingMap generic_args;
           BindingMap generic_args;
           if (!PatternMatch(type, *expected, binding.type().source_loc(),
           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())
             return CompilationError(binding.type().source_loc())
                    << "Type pattern '" << *type
                    << "Type pattern '" << *type
                    << "' does not match actual type '" << **expected << "'";
                    << "' does not match actual type '" << **expected << "'";
@@ -1921,17 +1944,40 @@ auto TypeChecker::TypeCheckPattern(
       SetValue(p, expr_value);
       SetValue(p, expr_value);
       return Success();
       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(&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(
       CARBON_ASSIGN_OR_RETURN(
           Nonnull<const Value*> pattern_value,
           Nonnull<const Value*> pattern_value,
-          InterpPattern(&let_var_pattern, arena_, trace_stream_));
-      SetValue(&let_var_pattern, pattern_value);
+          InterpPattern(&addr_pattern, arena_, trace_stream_));
+      SetValue(&addr_pattern, pattern_value);
       return Success();
       return Success();
   }
   }
 }
 }
@@ -2605,6 +2651,7 @@ static bool IsValidTypeForAliasTarget(Nonnull<const Value*> type) {
     case Value::Kind::ParameterizedEntityName:
     case Value::Kind::ParameterizedEntityName:
     case Value::Kind::MemberName:
     case Value::Kind::MemberName:
     case Value::Kind::BindingPlaceholderValue:
     case Value::Kind::BindingPlaceholderValue:
+    case Value::Kind::AddrValue:
     case Value::Kind::AlternativeConstructorValue:
     case Value::Kind::AlternativeConstructorValue:
     case Value::Kind::ContinuationValue:
     case Value::Kind::ContinuationValue:
     case Value::Kind::StringValue:
     case Value::Kind::StringValue:

+ 13 - 5
explorer/interpreter/value.cpp

@@ -31,7 +31,7 @@ auto StructValue::FindField(const std::string& name) const
 
 
 static auto GetMember(Nonnull<Arena*> arena, Nonnull<const Value*> v,
 static auto GetMember(Nonnull<Arena*> arena, Nonnull<const Value*> v,
                       const FieldPath::Component& field,
                       const FieldPath::Component& field,
-                      SourceLocation source_loc)
+                      SourceLocation source_loc, Nonnull<const Value*> me_value)
     -> ErrorOr<Nonnull<const Value*>> {
     -> ErrorOr<Nonnull<const Value*>> {
   const std::string& f = field.name();
   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()) {
         } else if ((*func)->declaration().is_method()) {
           // Found a method. Turn it into a bound method.
           // Found a method. Turn it into a bound method.
           const FunctionValue& m = cast<FunctionValue>(**func);
           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.type_args(),
                                               class_type.witnesses());
                                               class_type.witnesses());
         } else {
         } else {
@@ -131,12 +131,13 @@ static auto GetMember(Nonnull<Arena*> arena, Nonnull<const Value*> v,
 }
 }
 
 
 auto Value::GetMember(Nonnull<Arena*> arena, const FieldPath& path,
 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*>> {
     -> ErrorOr<Nonnull<const Value*>> {
   Nonnull<const Value*> value(this);
   Nonnull<const Value*> value(this);
   for (const FieldPath::Component& field : path.components_) {
   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;
   return value;
 }
 }
@@ -216,6 +217,11 @@ void Value::Print(llvm::raw_ostream& out) const {
       out << ">";
       out << ">";
       break;
       break;
     }
     }
+    case Value::Kind::AddrValue: {
+      const auto& addr = cast<AddrValue>(*this);
+      out << "Addr<" << addr.pattern() << ">";
+      break;
+    }
     case Value::Kind::AlternativeValue: {
     case Value::Kind::AlternativeValue: {
       const auto& alt = cast<AlternativeValue>(*this);
       const auto& alt = cast<AlternativeValue>(*this);
       out << "alt " << alt.choice_name() << "." << alt.alt_name() << " "
       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::PointerValue:
     case Value::Kind::LValue:
     case Value::Kind::LValue:
     case Value::Kind::BindingPlaceholderValue:
     case Value::Kind::BindingPlaceholderValue:
+    case Value::Kind::AddrValue:
     case Value::Kind::ContinuationValue:
     case Value::Kind::ContinuationValue:
     case Value::Kind::ParameterizedEntityName:
     case Value::Kind::ParameterizedEntityName:
     case Value::Kind::MemberName:
     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::NominalClassValue:
     case Value::Kind::AlternativeValue:
     case Value::Kind::AlternativeValue:
     case Value::Kind::BindingPlaceholderValue:
     case Value::Kind::BindingPlaceholderValue:
+    case Value::Kind::AddrValue:
     case Value::Kind::AlternativeConstructorValue:
     case Value::Kind::AlternativeConstructorValue:
     case Value::Kind::ContinuationValue:
     case Value::Kind::ContinuationValue:
     case Value::Kind::PointerValue:
     case Value::Kind::PointerValue:

+ 22 - 2
explorer/interpreter/value.h

@@ -61,6 +61,7 @@ class Value {
     ParameterizedEntityName,
     ParameterizedEntityName,
     MemberName,
     MemberName,
     BindingPlaceholderValue,
     BindingPlaceholderValue,
+    AddrValue,
     AlternativeConstructorValue,
     AlternativeConstructorValue,
     ContinuationValue,  // A first-class continuation value.
     ContinuationValue,  // A first-class continuation value.
     StringType,
     StringType,
@@ -80,9 +81,12 @@ class Value {
   LLVM_DUMP_METHOD void Dump() const { Print(llvm::errs()); }
   LLVM_DUMP_METHOD void Dump() const { Print(llvm::errs()); }
 
 
   // Returns the sub-Value specified by `path`, which must be a valid field
   // 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,
   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*>>;
       -> ErrorOr<Nonnull<const Value*>>;
 
 
   // Returns a copy of *this, but with the sub-Value specified by `path`
   // 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_;
   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.
 // The int type.
 class IntType : public Value {
 class IntType : public Value {
  public:
  public:

+ 2 - 0
explorer/syntax/lexer.lpp

@@ -33,6 +33,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 %s AFTER_OPERAND
 %s AFTER_OPERAND
 
 
 /* table-begin */
 /* table-begin */
+ADDR                 "addr"
 ALIAS                "alias"
 ALIAS                "alias"
 AMPERSAND            "&"
 AMPERSAND            "&"
 AND                  "and"
 AND                  "and"
@@ -138,6 +139,7 @@ string_literal        \"([^\\\"\n\v\f\r]|\\.)*\"
 %}
 %}
 
 
  /* table-begin */
  /* table-begin */
+{ADDR}                { return SIMPLE_TOKEN(ADDR);                }
 {ALIAS}               { return SIMPLE_TOKEN(ALIAS);               }
 {ALIAS}               { return SIMPLE_TOKEN(ALIAS);               }
 {AMPERSAND}           { return SIMPLE_TOKEN(AMPERSAND);           }
 {AMPERSAND}           { return SIMPLE_TOKEN(AMPERSAND);           }
 {AND}                 { return SIMPLE_TOKEN(AND);                 }
 {AND}                 { return SIMPLE_TOKEN(AND);                 }

+ 18 - 19
explorer/syntax/parser.ypp

@@ -142,6 +142,7 @@
 %type <Nonnull<Expression*>> if_expression
 %type <Nonnull<Expression*>> if_expression
 %type <Nonnull<Expression*>> expression
 %type <Nonnull<Expression*>> expression
 %type <Nonnull<GenericBinding*>> generic_binding
 %type <Nonnull<GenericBinding*>> generic_binding
+%type <Nonnull<Pattern*>> deduced_param
 %type <std::vector<Nonnull<AstNode*>>> deduced_params
 %type <std::vector<Nonnull<AstNode*>>> deduced_params
 %type <std::vector<Nonnull<AstNode*>>> impl_deduced_params
 %type <std::vector<Nonnull<AstNode*>>> impl_deduced_params
 %type <std::vector<Nonnull<AstNode*>>> deduced_param_list
 %type <std::vector<Nonnull<AstNode*>>> deduced_param_list
@@ -155,7 +156,7 @@
 %type <std::vector<FieldInitializer>> struct_type_literal_contents
 %type <std::vector<FieldInitializer>> struct_type_literal_contents
 %type <Nonnull<TupleLiteral*>> tuple
 %type <Nonnull<TupleLiteral*>> tuple
 %type <std::string> binding_lhs
 %type <std::string> binding_lhs
-%type <std::optional<Nonnull<BindingPattern*>>> receiver
+%type <std::optional<Nonnull<Pattern*>>> receiver
 %type <Nonnull<BindingPattern*>> variable_declaration
 %type <Nonnull<BindingPattern*>> variable_declaration
 %type <ParenContents<Expression>> paren_expression_base
 %type <ParenContents<Expression>> paren_expression_base
 %type <ParenContents<Expression>> paren_expression_contents
 %type <ParenContents<Expression>> paren_expression_contents
@@ -174,6 +175,7 @@
 %token
 %token
   // Most tokens have their spelling defined in lexer.lpp.
   // Most tokens have their spelling defined in lexer.lpp.
   // table-begin
   // table-begin
+  ADDR
   ALIAS
   ALIAS
   AMPERSAND
   AMPERSAND
   AND
   AND
@@ -797,27 +799,22 @@ generic_binding:
       $$ = arena->New<GenericBinding>(context.source_loc(), std::move($1), $3);
       $$ = 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:
 deduced_param_list:
   // Empty
   // Empty
-    { $$ = std::vector<Nonnull<AstNode*>>(); }
-| generic_binding
-    {
-      $$ = 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
+    { $$ = {}; }
+| deduced_param
+    { $$ = {$1}; }
+| deduced_param_list COMMA deduced_param
     {
     {
-      $$ = $1;
+      $$ = $1;  // TODO: can we std::move here?
       $$.push_back($3);
       $$.push_back($3);
     }
     }
 ;
 ;
@@ -838,6 +835,8 @@ receiver:
     { $$ = std::nullopt; }
     { $$ = std::nullopt; }
 | LEFT_CURLY_BRACE variable_declaration RIGHT_CURLY_BRACE
 | LEFT_CURLY_BRACE variable_declaration RIGHT_CURLY_BRACE
     { $$ = $2; }
     { $$ = $2; }
+| LEFT_CURLY_BRACE ADDR variable_declaration RIGHT_CURLY_BRACE
+    { $$ = arena->New<AddrPattern>(context.source_loc(), $3); }
 ;
 ;
 function_declaration:
 function_declaration:
   FN identifier deduced_params receiver maybe_empty_tuple_pattern return_term block
   FN identifier deduced_params receiver maybe_empty_tuple_pattern return_term block

+ 37 - 0
explorer/testdata/addr/fail-method-let.carbon

@@ -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 - 0
explorer/testdata/addr/fail-method-me-type.carbon

@@ -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 - 0
explorer/testdata/addr/method.carbon

@@ -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 - 0
explorer/testdata/addr/nested-method.carbon

@@ -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;
+}

+ 0 - 0
explorer/update_checks.py