From 2205fd52cedfcdfb67b956215b9424c43c4555da Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sat, 27 Feb 2021 13:32:03 -0800 Subject: [PATCH] [executable semantics] class-ify Declaration (#307) * [executable semantics] class-ify Declaration NFC (no functional change). Proof of concept that we can simplify code by replacing unions with safer, more regular types. Hand-rolled existentials (type-erasing CoW wrappers) are a follow-on step that will further simplify usage. Began adding `const` where possible, and replacing `std::string*` with `std::string`. Most `const`s can disappear as we replace reference semantics with value semantics, but in the meantime it's an important step in the right direction. --- executable_semantics/ast/declaration.cpp | 65 +++------ executable_semantics/ast/declaration.h | 78 +++++++---- executable_semantics/ast/expression.cpp | 2 +- executable_semantics/ast/expression.h | 2 +- .../ast/function_definition.cpp | 4 +- .../ast/function_definition.h | 7 +- .../interpreter/interpreter.cpp | 84 ++++++------ .../interpreter/interpreter.h | 2 +- .../interpreter/typecheck.cpp | 126 +++++++++--------- executable_semantics/interpreter/typecheck.h | 2 - executable_semantics/interpreter/value.cpp | 5 +- executable_semantics/interpreter/value.h | 2 +- executable_semantics/syntax.ypp | 8 +- executable_semantics/syntax_helpers.cpp | 14 +- 14 files changed, 191 insertions(+), 210 deletions(-) diff --git a/executable_semantics/ast/declaration.cpp b/executable_semantics/ast/declaration.cpp index 65b8f43c9c09..6345f853e780 100644 --- a/executable_semantics/ast/declaration.cpp +++ b/executable_semantics/ast/declaration.cpp @@ -8,57 +8,24 @@ namespace Carbon { -auto MakeFunDecl(FunctionDefinition* f) -> Declaration* { - auto* d = new Declaration(); - d->tag = DeclarationKind::FunctionDeclaration; - d->u.fun_def = f; - return d; -} +void FunctionDeclaration::Print() const { PrintFunDef(definition); } -auto MakeStructDecl(int line_num, std::string name, std::list* members) - -> Declaration* { - auto* d = new Declaration(); - d->tag = DeclarationKind::StructDeclaration; - d->u.struct_def = new StructDefinition(); - d->u.struct_def->line_num = line_num; - d->u.struct_def->name = new std::string(std::move(name)); - d->u.struct_def->members = members; - return d; -} - -auto MakeChoiceDecl(int line_num, std::string name, - std::list>* alts) - -> Declaration* { - auto* d = new Declaration(); - d->tag = DeclarationKind::ChoiceDeclaration; - d->u.choice_def.line_num = line_num; - d->u.choice_def.name = new std::string(std::move(name)); - d->u.choice_def.alternatives = alts; - return d; -} - -void PrintDecl(Declaration* d) { - switch (d->tag) { - case DeclarationKind::FunctionDeclaration: - PrintFunDef(d->u.fun_def); - break; - case DeclarationKind::StructDeclaration: - std::cout << "struct " << *d->u.struct_def->name << " {" << std::endl; - for (auto& member : *d->u.struct_def->members) { - PrintMember(member); - } - std::cout << "}" << std::endl; - break; - case DeclarationKind::ChoiceDeclaration: - std::cout << "choice " << *d->u.choice_def.name << " {" << std::endl; - for (auto& alternative : *d->u.choice_def.alternatives) { - std::cout << "alt " << alternative.first << " "; - PrintExp(alternative.second); - std::cout << ";" << std::endl; - } - std::cout << "}" << std::endl; - break; +void StructDeclaration::Print() const { + std::cout << "struct " << *definition.name << " {" << std::endl; + for (auto& member : *definition.members) { + PrintMember(member); } + std::cout << "}" << std::endl; +} + +void ChoiceDeclaration::Print() const { + std::cout << "choice " << name << " {" << std::endl; + for (auto& alternative : alternatives) { + std::cout << "alt " << alternative.first << " "; + PrintExp(alternative.second); + std::cout << ";" << std::endl; + } + std::cout << "}" << std::endl; } } // namespace Carbon diff --git a/executable_semantics/ast/declaration.h b/executable_semantics/ast/declaration.h index b4df411cdece..cc2940866dfb 100644 --- a/executable_semantics/ast/declaration.h +++ b/executable_semantics/ast/declaration.h @@ -14,36 +14,64 @@ namespace Carbon { -enum class DeclarationKind { - FunctionDeclaration, - StructDeclaration, - ChoiceDeclaration -}; +struct Value; +template +struct AssocList; +using Address = unsigned int; +using TypeEnv = AssocList; +using Env = AssocList; + +/// TODO:explain this. Also name it if necessary. Consult with jsiek. +using ExecutionEnvironment = std::pair; struct Declaration { - DeclarationKind tag; - union { - struct FunctionDefinition* fun_def; - - struct StructDefinition* struct_def; - - struct { - int line_num; - std::string* name; - std::list>* alternatives; - } choice_def; - - } u; + virtual void Print() const = 0; + virtual auto Name() const -> std::string = 0; + virtual auto TypeChecked(TypeEnv* env, Env* ct_env) const + -> const Declaration* = 0; + virtual void InitGlobals(Env*& globals) const = 0; + virtual auto TopLevel(ExecutionEnvironment&) const -> void = 0; }; -auto MakeFunDecl(struct FunctionDefinition* f) -> Declaration*; -auto MakeStructDecl(int line_num, std::string name, std::list* members) - -> Declaration*; -auto MakeChoiceDecl(int line_num, std::string name, - std::list>* alts) - -> Declaration*; +struct FunctionDeclaration : Declaration { + const FunctionDefinition* definition; + explicit FunctionDeclaration(const FunctionDefinition* definition) + : definition(definition) {} -void PrintDecl(Declaration* d); + void Print() const; + auto Name() const -> std::string; + auto TypeChecked(TypeEnv* env, Env* ct_env) const -> const Declaration*; + void InitGlobals(Env*& globals) const; + auto TopLevel(ExecutionEnvironment&) const -> void; +}; + +struct StructDeclaration : Declaration { + StructDefinition definition; + StructDeclaration(int line_num, std::string name, std::list* members) + : definition{line_num, new std::string(name), members} {} + + void Print() const; + auto Name() const -> std::string; + auto TypeChecked(TypeEnv* env, Env* ct_env) const -> const Declaration*; + void InitGlobals(Env*& globals) const; + auto TopLevel(ExecutionEnvironment&) const -> void; +}; + +struct ChoiceDeclaration : Declaration { + int line_num; + std::string name; + std::list> alternatives; + + ChoiceDeclaration(int line_num, std::string name, + std::list> alternatives) + : line_num(line_num), name(name), alternatives(alternatives) {} + + void Print() const; + auto Name() const -> std::string; + auto TypeChecked(TypeEnv* env, Env* ct_env) const -> const Declaration*; + void InitGlobals(Env*& globals) const; + auto TopLevel(ExecutionEnvironment&) const -> void; +}; } // namespace Carbon diff --git a/executable_semantics/ast/expression.cpp b/executable_semantics/ast/expression.cpp index 8d71eb285b22..7cdf678a2ea9 100644 --- a/executable_semantics/ast/expression.cpp +++ b/executable_semantics/ast/expression.cpp @@ -197,7 +197,7 @@ static void PrintFields( } } -void PrintExp(Expression* e) { +void PrintExp(const Expression* e) { switch (e->tag) { case ExpressionKind::Index: PrintExp(e->u.index.aggregate); diff --git a/executable_semantics/ast/expression.h b/executable_semantics/ast/expression.h index ff40931b6d62..398fdcc9fd86 100644 --- a/executable_semantics/ast/expression.h +++ b/executable_semantics/ast/expression.h @@ -109,7 +109,7 @@ auto MakeFunType(int line_num, Expression* param, Expression* ret) -> Expression*; auto MakeAutoType(int line_num) -> Expression*; -void PrintExp(Expression* exp); +void PrintExp(const Expression* exp); } // namespace Carbon diff --git a/executable_semantics/ast/function_definition.cpp b/executable_semantics/ast/function_definition.cpp index d2d45116486b..b5484898564a 100644 --- a/executable_semantics/ast/function_definition.cpp +++ b/executable_semantics/ast/function_definition.cpp @@ -20,7 +20,7 @@ auto MakeFunDef(int line_num, std::string name, Expression* ret_type, return f; } -void PrintFunDefDepth(struct FunctionDefinition* f, int depth) { +void PrintFunDefDepth(const FunctionDefinition* f, int depth) { std::cout << "fn " << f->name << " "; PrintExp(f->param_pattern); std::cout << " -> "; @@ -34,6 +34,6 @@ void PrintFunDefDepth(struct FunctionDefinition* f, int depth) { } } -void PrintFunDef(struct 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 68b65e6c8b1b..001ba5e869e0 100644 --- a/executable_semantics/ast/function_definition.h +++ b/executable_semantics/ast/function_definition.h @@ -19,10 +19,9 @@ struct FunctionDefinition { }; auto MakeFunDef(int line_num, std::string name, Expression* ret_type, - Expression* param, Statement* body) - -> struct FunctionDefinition*; -void PrintFunDef(struct FunctionDefinition*); -void PrintFunDefDepth(struct FunctionDefinition*, int); + Expression* param, 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 49f2ddc18826..959f32acaa47 100644 --- a/executable_semantics/interpreter/interpreter.cpp +++ b/executable_semantics/interpreter/interpreter.cpp @@ -252,55 +252,49 @@ auto EvalPrim(Operator op, const std::vector& args, int line_num) Env* globals; -void InitGlobals(std::list* fs) { +void InitGlobals(std::list* fs) { globals = nullptr; - for (auto& iter : *fs) { - switch (iter->tag) { - case DeclarationKind::ChoiceDeclaration: { - auto d = iter; - auto alts = new VarValues(); - for (auto i = d->u.choice_def.alternatives->begin(); - i != d->u.choice_def.alternatives->end(); ++i) { - auto t = - ToType(d->u.choice_def.line_num, InterpExp(nullptr, i->second)); - alts->push_back(make_pair(i->first, t)); - } - auto ct = MakeChoiceTypeVal(d->u.choice_def.name, alts); - auto a = AllocateValue(ct); - globals = new Env(*d->u.choice_def.name, a, globals); - break; - } - case DeclarationKind::StructDeclaration: { - auto d = iter; - auto fields = new VarValues(); - auto methods = new VarValues(); - for (auto i = d->u.struct_def->members->begin(); - i != d->u.struct_def->members->end(); ++i) { - switch ((*i)->tag) { - case MemberKind::FieldMember: { - auto t = ToType(d->u.struct_def->line_num, - InterpExp(nullptr, (*i)->u.field.type)); - fields->push_back(make_pair(*(*i)->u.field.name, t)); - break; - } - } - } - auto st = MakeStructTypeVal(*d->u.struct_def->name, fields, methods); - auto a = AllocateValue(st); - globals = new Env(*d->u.struct_def->name, a, globals); - break; - } - case DeclarationKind::FunctionDeclaration: { - struct FunctionDefinition* fun = iter->u.fun_def; - Env* env = nullptr; - auto pt = InterpExp(env, fun->param_pattern); - auto f = MakeFunVal(fun->name, pt, fun->body); - Address a = AllocateValue(f); - globals = new Env(fun->name, a, globals); + for (auto d : *fs) { + d->InitGlobals(globals); + } +} + +auto ChoiceDeclaration::InitGlobals(Env*& globals) const -> void { + auto alts = new VarValues(); + for (auto kv : alternatives) { + auto t = ToType(line_num, InterpExp(nullptr, kv.second)); + alts->push_back(make_pair(kv.first, t)); + } + auto ct = MakeChoiceTypeVal(name, alts); + auto a = AllocateValue(ct); + globals = new Env(name, a, globals); +} + +auto StructDeclaration::InitGlobals(Env*& globals) const -> void { + auto fields = new VarValues(); + auto methods = new VarValues(); + for (auto i = definition.members->begin(); i != definition.members->end(); + ++i) { + switch ((*i)->tag) { + case MemberKind::FieldMember: { + auto t = + ToType(definition.line_num, InterpExp(nullptr, (*i)->u.field.type)); + fields->push_back(make_pair(*(*i)->u.field.name, t)); break; } } } + auto st = MakeStructTypeVal(*definition.name, fields, methods); + auto a = AllocateValue(st); + globals = new Env(*definition.name, a, globals); +} + +auto FunctionDeclaration::InitGlobals(Env*& globals) const -> void { + Env* env = nullptr; + auto pt = InterpExp(env, definition->param_pattern); + auto f = MakeFunVal(definition->name, pt, definition->body); + Address a = AllocateValue(f); + globals = new Env(definition->name, a, globals); } // { S, H} -> { { C, E, F} :: S, H} @@ -1325,7 +1319,7 @@ void Step() { } // Interpret the whole porogram. -auto InterpProgram(std::list* fs) -> int { +auto InterpProgram(std::list* fs) -> int { state = new State(); // Runtime state. std::cout << "********** initializing globals **********" << std::endl; InitGlobals(fs); diff --git a/executable_semantics/interpreter/interpreter.h b/executable_semantics/interpreter/interpreter.h index 668a770074d6..9c7875a41919 100644 --- a/executable_semantics/interpreter/interpreter.h +++ b/executable_semantics/interpreter/interpreter.h @@ -52,7 +52,7 @@ auto ToInteger(Value* v) -> int; /***** Interpreters *****/ -auto InterpProgram(std::list* fs) -> int; +auto InterpProgram(std::list* fs) -> int; auto InterpExp(Env* env, Expression* e) -> Value*; } // namespace Carbon diff --git a/executable_semantics/interpreter/typecheck.cpp b/executable_semantics/interpreter/typecheck.cpp index 1c8c9f78544a..38fd9aba380d 100644 --- a/executable_semantics/interpreter/typecheck.cpp +++ b/executable_semantics/interpreter/typecheck.cpp @@ -566,7 +566,7 @@ auto CheckOrEnsureReturn(Statement* stmt, bool void_return, int line_num) } } -auto TypeCheckFunDef(struct FunctionDefinition* f, TypeEnv* env, Env* ct_env) +auto TypeCheckFunDef(const FunctionDefinition* f, TypeEnv* env, Env* ct_env) -> struct FunctionDefinition* { auto param_res = TypeCheckExp(f->param_pattern, env, ct_env, nullptr, TCContext::PatternContext); @@ -583,7 +583,7 @@ auto TypeCheckFunDef(struct FunctionDefinition* f, TypeEnv* env, Env* ct_env) f->param_pattern, body); } -auto TypeOfFunDef(TypeEnv* env, Env* ct_env, struct FunctionDefinition* fun_def) +auto TypeOfFunDef(TypeEnv* env, Env* ct_env, const FunctionDefinition* fun_def) -> Value* { auto param_res = TypeCheckExp(fun_def->param_pattern, env, ct_env, nullptr, TCContext::PatternContext); @@ -596,7 +596,7 @@ auto TypeOfFunDef(TypeEnv* env, Env* ct_env, struct FunctionDefinition* fun_def) return MakeFunTypeVal(param_type, ret); } -auto TypeOfStructDef(struct StructDefinition* sd, TypeEnv* /*env*/, Env* ct_top) +auto TypeOfStructDef(const StructDefinition* sd, TypeEnv* /*env*/, Env* ct_top) -> Value* { auto fields = new VarValues(); auto methods = new VarValues(); @@ -609,85 +609,79 @@ auto TypeOfStructDef(struct StructDefinition* sd, TypeEnv* /*env*/, Env* ct_top) return MakeStructTypeVal(*sd->name, fields, methods); } -auto NameOfDecl(Declaration* d) -> std::string { - switch (d->tag) { - case DeclarationKind::FunctionDeclaration: - return d->u.fun_def->name; - case DeclarationKind::StructDeclaration: - return *d->u.struct_def->name; - case DeclarationKind::ChoiceDeclaration: - return *d->u.choice_def.name; - } +auto FunctionDeclaration::Name() const -> std::string { + return definition->name; } -auto TypeCheckDecl(Declaration* d, TypeEnv* env, Env* ct_env) -> Declaration* { - switch (d->tag) { - case DeclarationKind::StructDeclaration: { - auto members = new std::list(); - for (auto& member : *d->u.struct_def->members) { - switch (member->tag) { - case MemberKind::FieldMember: { - // TODO: Interpret the type expression and store the result. - members->push_back(member); - break; - } - } - } - return MakeStructDecl(d->u.struct_def->line_num, *d->u.struct_def->name, - members); +auto StructDeclaration::Name() const -> std::string { return *definition.name; } + +auto ChoiceDeclaration::Name() const -> std::string { return name; } + +auto StructDeclaration::TypeChecked(TypeEnv* env, Env* ct_env) const + -> const Declaration* { + auto fields = new std::list(); + for (auto& m : *definition.members) { + if (m->tag == MemberKind::FieldMember) { + // TODO: Interpret the type expression and store the result. + fields->push_back(m); } - case DeclarationKind::FunctionDeclaration: - return MakeFunDecl(TypeCheckFunDef(d->u.fun_def, env, ct_env)); - case DeclarationKind::ChoiceDeclaration: - return d; // TODO. } + return new StructDeclaration(definition.line_num, *definition.name, fields); +} + +auto FunctionDeclaration::TypeChecked(TypeEnv* env, Env* ct_env) const + -> const Declaration* { + return new FunctionDeclaration(TypeCheckFunDef(definition, env, ct_env)); +} + +auto ChoiceDeclaration::TypeChecked(TypeEnv* env, Env* ct_env) const + -> const Declaration* { + return this; // TODO. } auto TopLevel(std::list* fs) -> std::pair { - TypeEnv* top = nullptr; - Env* ct_top = nullptr; + ExecutionEnvironment tops = {nullptr, nullptr}; bool found_main = false; + for (auto d : *fs) { - if (NameOfDecl(d) == "main") { + if (d->Name() == "main") { found_main = true; } - switch (d->tag) { - case DeclarationKind::FunctionDeclaration: { - auto t = TypeOfFunDef(top, ct_top, d->u.fun_def); - top = new TypeEnv(NameOfDecl(d), t, top); - break; - } - case DeclarationKind::StructDeclaration: { - auto st = TypeOfStructDef(d->u.struct_def, top, ct_top); - Address a = AllocateValue(st); - ct_top = new Env(NameOfDecl(d), a, ct_top); // Is this obsolete? - auto params = MakeTupleTypeVal(st->u.struct_type.fields); - auto fun_ty = MakeFunTypeVal(params, st); - top = new TypeEnv(NameOfDecl(d), fun_ty, top); - break; - } - case DeclarationKind::ChoiceDeclaration: { - auto alts = new VarValues(); - for (auto i = d->u.choice_def.alternatives->begin(); - i != d->u.choice_def.alternatives->end(); ++i) { - auto t = - ToType(d->u.choice_def.line_num, InterpExp(ct_top, i->second)); - alts->push_back(std::make_pair(i->first, t)); - } - auto ct = MakeChoiceTypeVal(d->u.choice_def.name, alts); - Address a = AllocateValue(ct); - ct_top = new Env(NameOfDecl(d), a, ct_top); // Is this obsolete? - top = new TypeEnv(NameOfDecl(d), ct, top); - break; - } - } // switch (d->tag) - } // for + d->TopLevel(tops); + } + if (found_main == false) { std::cerr << "error, program must contain a function named `main`" << std::endl; exit(-1); } - return make_pair(top, ct_top); + return tops; +} + +auto FunctionDeclaration::TopLevel(ExecutionEnvironment& tops) const -> void { + auto t = TypeOfFunDef(tops.first, tops.second, definition); + tops.first = new TypeEnv(Name(), t, tops.first); +} + +auto StructDeclaration::TopLevel(ExecutionEnvironment& tops) const -> void { + auto st = TypeOfStructDef(&definition, tops.first, tops.second); + Address a = AllocateValue(st); + tops.second = new Env(Name(), a, tops.second); // Is this obsolete? + auto params = MakeTupleTypeVal(st->u.struct_type.fields); + auto fun_ty = MakeFunTypeVal(params, st); + tops.first = new TypeEnv(Name(), fun_ty, tops.first); +} + +auto ChoiceDeclaration::TopLevel(ExecutionEnvironment& tops) const -> void { + auto alts = new VarValues(); + for (auto a : alternatives) { + auto t = ToType(line_num, InterpExp(tops.second, a.second)); + alts->push_back(std::make_pair(a.first, t)); + } + auto ct = MakeChoiceTypeVal(name, alts); + Address a = AllocateValue(ct); + tops.second = new Env(Name(), a, tops.second); // Is this obsolete? + tops.first = new TypeEnv(Name(), ct, tops.first); } } // namespace Carbon diff --git a/executable_semantics/interpreter/typecheck.h b/executable_semantics/interpreter/typecheck.h index b74cc7612256..a4494f168f54 100644 --- a/executable_semantics/interpreter/typecheck.h +++ b/executable_semantics/interpreter/typecheck.h @@ -45,8 +45,6 @@ auto TypeCheckStmt(Statement*, TypeEnv*, Env*, Value*) -> TCStatement; auto TypeCheckFunDef(struct FunctionDefinition*, TypeEnv*) -> struct FunctionDefinition*; -auto TypeCheckDecl(Declaration* d, TypeEnv* env, Env* ct_env) -> Declaration*; - auto TopLevel(std::list* fs) -> std::pair; void PrintErrorString(const std::string& s); diff --git a/executable_semantics/interpreter/value.cpp b/executable_semantics/interpreter/value.cpp index 215b3400707d..7c6ba47eb977 100644 --- a/executable_semantics/interpreter/value.cpp +++ b/executable_semantics/interpreter/value.cpp @@ -197,13 +197,14 @@ auto MakeVoidTypeVal() -> Value* { return v; } -auto MakeChoiceTypeVal(std::string* name, +auto MakeChoiceTypeVal(std::string name, std::list>* alts) -> Value* { auto* v = new Value(); v->alive = true; v->tag = ValKind::ChoiceTV; - v->u.choice_type.name = name; + // Transitional leak: when we get rid of all pointers, this will disappear. + v->u.choice_type.name = new std::string(name); v->u.choice_type.alternatives = alts; return v; } diff --git a/executable_semantics/interpreter/value.h b/executable_semantics/interpreter/value.h index 8873db7190c7..7362aa7d1738 100644 --- a/executable_semantics/interpreter/value.h +++ b/executable_semantics/interpreter/value.h @@ -124,7 +124,7 @@ auto MakeStructTypeVal(std::string name, VarValues* fields, VarValues* methods) -> Value*; auto MakeTupleTypeVal(VarValues* fields) -> Value*; auto MakeVoidTypeVal() -> Value*; -auto MakeChoiceTypeVal(std::string* name, VarValues* alts) -> Value*; +auto MakeChoiceTypeVal(std::string name, VarValues* alts) -> Value*; void PrintValue(Value* val, std::ostream& out); diff --git a/executable_semantics/syntax.ypp b/executable_semantics/syntax.ypp index 38ca71feffb6..5cb7ea61e6b9 100644 --- a/executable_semantics/syntax.ypp +++ b/executable_semantics/syntax.ypp @@ -312,13 +312,13 @@ alternative_list: ; declaration: function_definition - { $$ = Carbon::MakeFunDecl($1); } + { $$ = new Carbon::FunctionDeclaration{$1}; } | function_declaration - { $$ = Carbon::MakeFunDecl($1); } + { $$ = new Carbon::FunctionDeclaration{$1}; } | STRUCT identifier '{' member_list '}' - { $$ = Carbon::MakeStructDecl(yylineno, $2, $4); } + { $$ = new Carbon::StructDeclaration{yylineno, $2, $4}; } | CHOICE identifier '{' alternative_list '}' - { $$ = Carbon::MakeChoiceDecl(yylineno, $2, $4); } + { $$ = new Carbon::ChoiceDeclaration{yylineno, $2, std::list(*$4)}; } ; declaration_list: // Empty diff --git a/executable_semantics/syntax_helpers.cpp b/executable_semantics/syntax_helpers.cpp index dfef32344293..b5dcc0cc8c13 100644 --- a/executable_semantics/syntax_helpers.cpp +++ b/executable_semantics/syntax_helpers.cpp @@ -20,22 +20,22 @@ void PrintSyntaxError(char* error, int line_num) { void ExecProgram(std::list* fs) { std::cout << "********** source program **********" << std::endl; - for (const auto& decl : *fs) { - PrintDecl(decl); + for (const auto decl : *fs) { + decl->Print(); } std::cout << "********** type checking **********" << std::endl; state = new State(); // Compile-time state. std::pair p = TopLevel(fs); TypeEnv* top = p.first; Env* ct_top = p.second; - std::list new_decls; - for (const auto& i : *fs) { - new_decls.push_back(TypeCheckDecl(i, top, ct_top)); + std::list new_decls; + for (const auto i : *fs) { + new_decls.push_back(i->TypeChecked(top, ct_top)); } std::cout << std::endl; std::cout << "********** type checking complete **********" << std::endl; - for (const auto& decl : new_decls) { - PrintDecl(decl); + for (const auto decl : new_decls) { + decl->Print(); } std::cout << "********** starting execution **********" << std::endl; int result = InterpProgram(&new_decls);