Просмотр исходного кода

Migrate declaration parsing to value semantics (#614)

* Use Expression by value in FunctionDefinition
* Migrate choice declarations to value semantics
* Migrate Declaration parsing to value semantics
Geoff Romer 4 лет назад
Родитель
Сommit
fa5b9cd553

+ 1 - 1
executable_semantics/ast/abstract_syntax_tree.h

@@ -10,7 +10,7 @@
 #include "executable_semantics/ast/declaration.h"
 
 namespace Carbon {
-using AST = std::list<Carbon::Declaration>*;
+using AST = std::list<Carbon::Declaration>;
 }
 
 #endif  // EXECUTABLE_SEMANTICS_AST_ABSTRACT_SYNTAX_TREE_H_

+ 3 - 3
executable_semantics/ast/declaration.cpp

@@ -20,9 +20,9 @@ void StructDeclaration::Print() const {
 
 void ChoiceDeclaration::Print() const {
   std::cout << "choice " << name << " {" << std::endl;
-  for (auto& alternative : alternatives) {
-    std::cout << "alt " << alternative.first << " ";
-    PrintExp(alternative.second);
+  for (const auto& [name, signature] : alternatives) {
+    std::cout << "alt " << name << " ";
+    PrintExp(&signature);
     std::cout << ";" << std::endl;
   }
   std::cout << "}" << std::endl;

+ 19 - 10
executable_semantics/ast/declaration.h

@@ -13,6 +13,10 @@
 #include "executable_semantics/ast/struct_definition.h"
 #include "executable_semantics/interpreter/dictionary.h"
 
+namespace yy {
+class parser;
+}
+
 namespace Carbon {
 
 struct Value;
@@ -56,7 +60,7 @@ class Declaration {
   // Add an entry in the compile time global symbol tables for this declaration.
   auto TopLevel(TypeCheckContext& e) const -> void { return box->TopLevel(e); }
 
- private:  // types
+ private:
   // A base class that erases the type of a `Boxed<Content>`, where `Content`
   // satisfies the Declaration concept.
   struct Box {
@@ -95,15 +99,21 @@ class Declaration {
     }
   };
 
- private:  // data members
+  // Constructs an instance in a "partially formed" state, which can only be
+  // assigned to or destroyed.
+  Declaration() = default;
+
+  // Give Bison access to the default constructor.
+  friend class yy::parser;
+
   // Note: the pointee is const as long as we have no mutating methods. When
   std::shared_ptr<const Box> box;
 };
 
 struct FunctionDeclaration {
-  const FunctionDefinition* definition;
-  explicit FunctionDeclaration(const FunctionDefinition* definition)
-      : definition(definition) {}
+  FunctionDefinition definition;
+  explicit FunctionDeclaration(FunctionDefinition definition)
+      : definition(std::move(definition)) {}
 
   auto Print() const -> void;
   auto Name() const -> std::string;
@@ -127,12 +137,11 @@ struct StructDeclaration {
 struct ChoiceDeclaration {
   int line_num;
   std::string name;
-  std::list<std::pair<std::string, const Expression*>> alternatives;
+  std::list<std::pair<std::string, Expression>> alternatives;
 
-  ChoiceDeclaration(
-      int line_num, std::string name,
-      std::list<std::pair<std::string, const Expression*>> alternatives)
-      : line_num(line_num), name(name), alternatives(alternatives) {}
+  ChoiceDeclaration(int line_num, std::string name,
+                    std::list<std::pair<std::string, Expression>> alternatives)
+      : line_num(line_num), name(name), alternatives(std::move(alternatives)) {}
 
   void Print() const;
   auto Name() const -> std::string;

+ 16 - 16
executable_semantics/ast/function_definition.cpp

@@ -8,32 +8,32 @@
 
 namespace Carbon {
 
-auto MakeFunDef(int line_num, std::string name, const Expression* ret_type,
-                const Expression* param_pattern, const Statement* body)
-    -> struct FunctionDefinition* {
-  auto* f = new struct FunctionDefinition();
-  f->line_num = line_num;
-  f->name = std::move(name);
-  f->return_type = ret_type;
-  f->param_pattern = param_pattern;
-  f->body = body;
+auto MakeFunDef(int line_num, std::string name, Expression ret_type,
+                Expression param_pattern, const Statement* body)
+    -> FunctionDefinition {
+  FunctionDefinition f;
+  f.line_num = line_num;
+  f.name = std::move(name);
+  f.return_type = std::move(ret_type);
+  f.param_pattern = std::move(param_pattern);
+  f.body = body;
   return f;
 }
 
-void PrintFunDefDepth(const FunctionDefinition* f, int depth) {
-  std::cout << "fn " << f->name << " ";
-  PrintExp(f->param_pattern);
+void PrintFunDefDepth(const FunctionDefinition& f, int depth) {
+  std::cout << "fn " << f.name << " ";
+  PrintExp(&f.param_pattern);
   std::cout << " -> ";
-  PrintExp(f->return_type);
-  if (f->body) {
+  PrintExp(&f.return_type);
+  if (f.body) {
     std::cout << " {" << std::endl;
-    PrintStatement(f->body, depth);
+    PrintStatement(f.body, depth);
     std::cout << std::endl << "}" << std::endl;
   } else {
     std::cout << ";" << std::endl;
   }
 }
 
-void PrintFunDef(const FunctionDefinition* f) { PrintFunDefDepth(f, -1); }
+void PrintFunDef(const FunctionDefinition& f) { PrintFunDefDepth(f, -1); }
 
 }  // namespace Carbon

+ 6 - 7
executable_semantics/ast/function_definition.h

@@ -13,16 +13,15 @@ namespace Carbon {
 struct FunctionDefinition {
   int line_num;
   std::string name;
-  const Expression* param_pattern;
-  const Expression* return_type;
+  Expression param_pattern;
+  Expression return_type;
   const Statement* body;
 };
 
-auto MakeFunDef(int line_num, std::string name, const Expression* ret_type,
-                const Expression* param, const Statement* body)
-    -> FunctionDefinition*;
-void PrintFunDef(const FunctionDefinition*);
-void PrintFunDefDepth(const FunctionDefinition*, int);
+auto MakeFunDef(int line_num, std::string name, Expression ret_type,
+                Expression param, const Statement* body) -> FunctionDefinition;
+void PrintFunDef(const FunctionDefinition&);
+void PrintFunDefDepth(const FunctionDefinition&, int);
 
 }  // namespace Carbon
 

+ 6 - 6
executable_semantics/interpreter/interpreter.cpp

@@ -314,9 +314,9 @@ void InitGlobals(std::list<Declaration>* fs) {
 
 auto ChoiceDeclaration::InitGlobals(Env& globals) const -> void {
   auto alts = new VarValues();
-  for (auto kv : alternatives) {
-    auto t = InterpExp(Env(), kv.second);
-    alts->push_back(make_pair(kv.first, t));
+  for (const auto& [name, signature] : alternatives) {
+    auto t = InterpExp(Env(), &signature);
+    alts->push_back(make_pair(name, t));
   }
   auto ct = Value::MakeChoiceTypeVal(name, alts);
   auto a = state->heap.AllocateValue(ct);
@@ -342,10 +342,10 @@ auto StructDeclaration::InitGlobals(Env& globals) const -> void {
 }
 
 auto FunctionDeclaration::InitGlobals(Env& globals) const -> void {
-  auto pt = InterpExp(globals, definition->param_pattern);
-  auto f = Value::MakeFunVal(definition->name, pt, definition->body);
+  auto pt = InterpExp(globals, &definition.param_pattern);
+  auto f = Value::MakeFunVal(definition.name, pt, definition.body);
   Address a = state->heap.AllocateValue(f);
-  globals.Set(definition->name, a);
+  globals.Set(definition.name, a);
 }
 
 // Adds an entry in `globals` mapping the variable's name to the

+ 14 - 13
executable_semantics/interpreter/typecheck.cpp

@@ -664,9 +664,9 @@ auto CheckOrEnsureReturn(const Statement* stmt, bool void_return, int line_num)
 
 auto TypeCheckFunDef(const FunctionDefinition* f, TypeEnv types, Env values)
     -> struct FunctionDefinition* {
-  auto param_res = TypeCheckExp(f->param_pattern, types, values, nullptr,
+  auto param_res = TypeCheckExp(&f->param_pattern, types, values, nullptr,
                                 TCContext::PatternContext);
-  auto return_type = InterpExp(values, f->return_type);
+  auto return_type = InterpExp(values, &f->return_type);
   if (f->name == "main") {
     ExpectType(f->line_num, "return type of `main`", Value::MakeIntTypeVal(),
                return_type);
@@ -675,18 +675,19 @@ auto TypeCheckFunDef(const FunctionDefinition* f, TypeEnv types, Env values)
   auto res = TypeCheckStmt(f->body, param_res.types, values, return_type);
   bool void_return = TypeEqual(return_type, Value::MakeUnitTypeVal());
   auto body = CheckOrEnsureReturn(res.stmt, void_return, f->line_num);
-  return MakeFunDef(f->line_num, f->name, ReifyType(return_type, f->line_num),
-                    f->param_pattern, body);
+  return new FunctionDefinition(MakeFunDef(f->line_num, f->name,
+                                           *ReifyType(return_type, f->line_num),
+                                           f->param_pattern, body));
 }
 
 auto TypeOfFunDef(TypeEnv types, Env values, const FunctionDefinition* fun_def)
     -> const Value* {
-  auto param_res = TypeCheckExp(fun_def->param_pattern, types, values, nullptr,
+  auto param_res = TypeCheckExp(&fun_def->param_pattern, types, values, nullptr,
                                 TCContext::PatternContext);
-  auto ret = InterpExp(values, fun_def->return_type);
+  auto ret = InterpExp(values, &fun_def->return_type);
   if (ret->tag == ValKind::AutoTV) {
     auto f = TypeCheckFunDef(fun_def, types, values);
-    ret = InterpExp(values, f->return_type);
+    ret = InterpExp(values, &f->return_type);
   }
   return Value::MakeFunTypeVal(param_res.type, ret);
 }
@@ -705,7 +706,7 @@ auto TypeOfStructDef(const StructDefinition* sd, TypeEnv /*types*/, Env ct_top)
 }
 
 auto FunctionDeclaration::Name() const -> std::string {
-  return definition->name;
+  return definition.name;
 }
 
 auto StructDeclaration::Name() const -> std::string { return *definition.name; }
@@ -729,7 +730,7 @@ auto StructDeclaration::TypeChecked(TypeEnv types, Env values) const
 
 auto FunctionDeclaration::TypeChecked(TypeEnv types, Env values) const
     -> Declaration {
-  return FunctionDeclaration(TypeCheckFunDef(definition, types, values));
+  return FunctionDeclaration(*TypeCheckFunDef(&definition, types, values));
 }
 
 auto ChoiceDeclaration::TypeChecked(TypeEnv types, Env values) const
@@ -770,7 +771,7 @@ auto TopLevel(std::list<Declaration>* fs) -> TypeCheckContext {
 }
 
 auto FunctionDeclaration::TopLevel(TypeCheckContext& tops) const -> void {
-  auto t = TypeOfFunDef(tops.types, tops.values, definition);
+  auto t = TypeOfFunDef(tops.types, tops.values, &definition);
   tops.types.Set(Name(), t);
   InitGlobals(tops.values);
 }
@@ -790,9 +791,9 @@ auto StructDeclaration::TopLevel(TypeCheckContext& tops) const -> void {
 
 auto ChoiceDeclaration::TopLevel(TypeCheckContext& tops) const -> void {
   auto alts = new VarValues();
-  for (auto a : alternatives) {
-    auto t = InterpExp(tops.values, a.second);
-    alts->push_back(std::make_pair(a.first, t));
+  for (const auto& [name, signature] : alternatives) {
+    auto t = InterpExp(tops.values, &signature);
+    alts->push_back(std::make_pair(name, t));
   }
   auto ct = Value::MakeChoiceTypeVal(name, alts);
   Address a = state->heap.AllocateValue(ct);

+ 1 - 1
executable_semantics/main.cpp

@@ -32,5 +32,5 @@ int main(int argc, char* argv[]) {
   }
 
   // Typecheck and run the parsed program.
-  Carbon::ExecProgram(std::get<Carbon::AST>(ast_or_error));
+  Carbon::ExecProgram(&std::get<Carbon::AST>(ast_or_error));
 }

+ 24 - 24
executable_semantics/syntax/parser.ypp

@@ -92,10 +92,10 @@ void yy::parser::error(
 %token <int> integer_literal
 %token <char*> identifier
 %type <char*> designator
-%type <Carbon::Declaration*> declaration
-%type <Carbon::FunctionDefinition*> function_declaration
-%type <Carbon::FunctionDefinition*> function_definition
-%type <std::list<Carbon::Declaration>*> declaration_list
+%type <Carbon::Declaration> declaration
+%type <Carbon::FunctionDefinition> function_declaration
+%type <Carbon::FunctionDefinition> function_definition
+%type <std::list<Carbon::Declaration>> declaration_list
 %type <const Carbon::Statement*> statement
 %type <const Carbon::Statement*> optional_else
 %type <const Carbon::Statement*> statement_list
@@ -110,8 +110,8 @@ void yy::parser::error(
 %type <Carbon::FieldInitializer> field_initializer
 %type <Carbon::ParenContents> paren_contents
 %type <std::vector<Carbon::FieldInitializer>> paren_contents_without_trailing_comma
-%type <std::pair<std::string, const Carbon::Expression*>*> alternative
-%type <std::list<std::pair<std::string, const Carbon::Expression*>>*> alternative_list
+%type <std::pair<std::string, Carbon::Expression>> alternative
+%type <std::list<std::pair<std::string, Carbon::Expression>>> alternative_list
 %type <std::pair<const Carbon::Expression*, const Carbon::Statement*>*> clause
 %type <std::list<std::pair<const Carbon::Expression*, const Carbon::Statement*>>*> clause_list
 %token END_OF_FILE 0
@@ -356,16 +356,16 @@ return_type:
 ;
 function_definition:
   FN identifier tuple return_type "{" statement_list "}"
-    { $$ = MakeFunDef(yylineno, $2, $4, $3, $6); }
+    { $$ = MakeFunDef(yylineno, $2, *$4, *$3, $6); }
 | FN identifier tuple DBLARROW expression ";"
     {
-      $$ = Carbon::MakeFunDef(yylineno, $2, Carbon::Expression::MakeAutoType(yylineno), $3,
+      $$ = Carbon::MakeFunDef(yylineno, $2, *Carbon::Expression::MakeAutoType(yylineno), *$3,
                               Carbon::Statement::MakeReturn(yylineno, *$5));
     }
 ;
 function_declaration:
   FN identifier tuple return_type ";"
-    { $$ = MakeFunDef(yylineno, $2, $4, $3, 0); }
+    { $$ = MakeFunDef(yylineno, $2, *$4, *$3, 0); }
 ;
 variable_declaration: identifier ":" expression
     { $$ = MakeField(yylineno, $1, $3); }
@@ -381,52 +381,52 @@ member_list:
 ;
 alternative:
   identifier tuple
-    { $$ = new std::pair<std::string, const Carbon::Expression*>($1, $2); }
+    { $$ = std::pair<std::string, Carbon::Expression>($1, *$2); }
 | identifier
     {
-      $$ = new std::pair<std::string, const Carbon::Expression*>(
-          $1, Carbon::Expression::MakeTuple(yylineno, {}));
+      $$ = std::pair<std::string, Carbon::Expression>(
+          $1, *Carbon::Expression::MakeTuple(yylineno, {}));
     }
 ;
 alternative_list:
   // Empty
-    { $$ = new std::list<std::pair<std::string, const Carbon::Expression*>>(); }
+    { $$ = std::list<std::pair<std::string, Carbon::Expression>>(); }
 | alternative
     {
-      $$ = new std::list<std::pair<std::string, const Carbon::Expression*>>();
-      $$->push_front(*$1);
+      $$ = std::list<std::pair<std::string, Carbon::Expression>>();
+      $$.push_front($1);
     }
 | alternative "," alternative_list
-    { $$ = $3; $$->push_front(*$1); }
+    { $$ = std::move($3); $$.push_front($1); }
 ;
 declaration:
   function_definition
-    { $$ = new Carbon::Declaration(Carbon::FunctionDeclaration{$1}); }
+    { $$ = Carbon::Declaration(Carbon::FunctionDeclaration{$1}); }
 | function_declaration
-    { $$ = new Carbon::Declaration(Carbon::FunctionDeclaration{$1}); }
+    { $$ = Carbon::Declaration(Carbon::FunctionDeclaration{$1}); }
 | STRUCT identifier "{" member_list "}"
     {
-      $$ = new Carbon::Declaration(
+      $$ = Carbon::Declaration(
         Carbon::StructDeclaration{yylineno, $2, $4});
     }
 | CHOICE identifier "{" alternative_list "}"
     {
-      $$ = new Carbon::Declaration(
-        Carbon::ChoiceDeclaration{yylineno, $2, std::list(*$4)});
+      $$ = Carbon::Declaration(
+        Carbon::ChoiceDeclaration{yylineno, $2, $4});
     }
 | VAR variable_declaration "=" expression ";"
     {
-      $$ = new Carbon::Declaration(
+      $$ = Carbon::Declaration(
         Carbon::VariableDeclaration(yylineno, *$2->u.field.name, $2->u.field.type, $4));
     }
 ;
 declaration_list:
   // Empty
-    { $$ = new std::list<Carbon::Declaration>(); }
+    { $$ = std::list<Carbon::Declaration>(); }
 | declaration declaration_list
     {
       $$ = $2;
-      $$->push_front(*$1);
+      $$.push_front($1);
     }
 ;
 %%