Value semantics for Declaration. (#313)

This change creates an unpleasant amount of boilerplate where `Declaration` is declared, in exchange for being able to—very pleasantly—treat it as a simple value that composes with other values everywhere it is used. Applying this technique broadly will pay off in code comprehensibility; once it has been done for all things being new'd, pointers disappear and references are only needed as an idiomatic approximation of inout. The unpleasant code grows only when new polymorphic operations are added, and then only a bit, and is an idiom whose details can readily be ignored once in place. The pleasant code pervades the codebase.

Too bad we don't have existential types in C++ ;-)
This commit is contained in:
Dave Abrahams
2021-02-28 11:29:38 -08:00
committed by GitHub
parent 2afbfd6146
commit 102ea3ccaf
8 changed files with 112 additions and 48 deletions
+8 -8
View File
@@ -18,24 +18,24 @@ void PrintSyntaxError(char* error, int line_num) {
exit(-1);
}
void ExecProgram(std::list<Declaration*>* fs) {
void ExecProgram(std::list<Declaration>* fs) {
std::cout << "********** source program **********" << std::endl;
for (const auto decl : *fs) {
decl->Print();
for (const auto& decl : *fs) {
decl.Print();
}
std::cout << "********** type checking **********" << std::endl;
state = new State(); // Compile-time state.
std::pair<TypeEnv*, Env*> p = TopLevel(fs);
TypeEnv* top = p.first;
Env* ct_top = p.second;
std::list<const Declaration*> new_decls;
for (const auto i : *fs) {
new_decls.push_back(i->TypeChecked(top, ct_top));
std::list<Declaration> new_decls;
for (const auto& decl : *fs) {
new_decls.push_back(decl.TypeChecked(top, ct_top));
}
std::cout << std::endl;
std::cout << "********** type checking complete **********" << std::endl;
for (const auto decl : new_decls) {
decl->Print();
for (const auto& decl : new_decls) {
decl.Print();
}
std::cout << "********** starting execution **********" << std::endl;
int result = InterpProgram(&new_decls);