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
This commit is contained in:
Geoff Romer
2021-06-30 13:09:12 -07:00
committed by GitHub
parent 7e70a0335e
commit fa5b9cd553
9 changed files with 90 additions and 81 deletions
@@ -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
View File
@@ -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
View File
@@ -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;
@@ -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
@@ -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
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
}
;
%%