diff --git a/executable_semantics/ast/abstract_syntax_tree.h b/executable_semantics/ast/abstract_syntax_tree.h index 009684cb9d23..f89c65783118 100644 --- a/executable_semantics/ast/abstract_syntax_tree.h +++ b/executable_semantics/ast/abstract_syntax_tree.h @@ -10,7 +10,7 @@ #include "executable_semantics/ast/declaration.h" namespace Carbon { -using AST = std::list*; +using AST = std::list; } #endif // EXECUTABLE_SEMANTICS_AST_ABSTRACT_SYNTAX_TREE_H_ diff --git a/executable_semantics/ast/declaration.cpp b/executable_semantics/ast/declaration.cpp index 30ef07a5fb1e..b0c2a0c78576 100644 --- a/executable_semantics/ast/declaration.cpp +++ b/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; diff --git a/executable_semantics/ast/declaration.h b/executable_semantics/ast/declaration.h index 3918edd7f47b..6b7387bb9ddb 100644 --- a/executable_semantics/ast/declaration.h +++ b/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`, 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 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> alternatives; + std::list> alternatives; - ChoiceDeclaration( - int line_num, std::string name, - std::list> alternatives) - : line_num(line_num), name(name), alternatives(alternatives) {} + ChoiceDeclaration(int line_num, std::string name, + std::list> alternatives) + : line_num(line_num), name(name), alternatives(std::move(alternatives)) {} void Print() const; auto Name() const -> std::string; diff --git a/executable_semantics/ast/function_definition.cpp b/executable_semantics/ast/function_definition.cpp index 47b34daafd75..c48e034700f1 100644 --- a/executable_semantics/ast/function_definition.cpp +++ b/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 diff --git a/executable_semantics/ast/function_definition.h b/executable_semantics/ast/function_definition.h index 377e3c951d03..c1587a36e167 100644 --- a/executable_semantics/ast/function_definition.h +++ b/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 diff --git a/executable_semantics/interpreter/interpreter.cpp b/executable_semantics/interpreter/interpreter.cpp index 58c830f81d48..1a59b97b99d7 100644 --- a/executable_semantics/interpreter/interpreter.cpp +++ b/executable_semantics/interpreter/interpreter.cpp @@ -314,9 +314,9 @@ void InitGlobals(std::list* 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 diff --git a/executable_semantics/interpreter/typecheck.cpp b/executable_semantics/interpreter/typecheck.cpp index 4675d36ede10..0901846f852e 100644 --- a/executable_semantics/interpreter/typecheck.cpp +++ b/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* 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); diff --git a/executable_semantics/main.cpp b/executable_semantics/main.cpp index 4f1b5ddc26b3..f456eaab094e 100644 --- a/executable_semantics/main.cpp +++ b/executable_semantics/main.cpp @@ -32,5 +32,5 @@ int main(int argc, char* argv[]) { } // Typecheck and run the parsed program. - Carbon::ExecProgram(std::get(ast_or_error)); + Carbon::ExecProgram(&std::get(ast_or_error)); } diff --git a/executable_semantics/syntax/parser.ypp b/executable_semantics/syntax/parser.ypp index f629ab90c232..f74757fd1e7d 100644 --- a/executable_semantics/syntax/parser.ypp +++ b/executable_semantics/syntax/parser.ypp @@ -92,10 +92,10 @@ void yy::parser::error( %token integer_literal %token identifier %type designator -%type declaration -%type function_declaration -%type function_definition -%type *> declaration_list +%type declaration +%type function_declaration +%type function_definition +%type > declaration_list %type statement %type optional_else %type statement_list @@ -110,8 +110,8 @@ void yy::parser::error( %type field_initializer %type paren_contents %type > paren_contents_without_trailing_comma -%type *> alternative -%type >*> alternative_list +%type > alternative +%type >> alternative_list %type *> clause %type >*> 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($1, $2); } + { $$ = std::pair($1, *$2); } | identifier { - $$ = new std::pair( - $1, Carbon::Expression::MakeTuple(yylineno, {})); + $$ = std::pair( + $1, *Carbon::Expression::MakeTuple(yylineno, {})); } ; alternative_list: // Empty - { $$ = new std::list>(); } + { $$ = std::list>(); } | alternative { - $$ = new std::list>(); - $$->push_front(*$1); + $$ = std::list>(); + $$.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(); } + { $$ = std::list(); } | declaration declaration_list { $$ = $2; - $$->push_front(*$1); + $$.push_front($1); } ; %%