From b0a01d2fb7ca030130fa9fedfcef287e33d87be5 Mon Sep 17 00:00:00 2001 From: Stefano Sanfilippo Date: Thu, 5 Mar 2015 01:16:40 +0100 Subject: [PATCH] Decouple AST nodes from representation. 1. adding getters to all node properties. 2. extracting an Emitter interface. 3. moving all C++ codegen features to a CppEmitter. All list template specializations typedefs have been removed for increased readability. A dependency on Boost is introduced for boost::optional, which is required in the AST getters API. --- CMakeLists.txt | 13 +- CppEmitter.cpp | 381 +++++++++++++++++++++++++++++++++++++++ CppEmitter.hpp | 93 ++++++++++ Emitter.hpp | 113 ++++++++++++ Monicelli.ypp | 25 +-- Nodes.cpp | 267 ---------------------------- Nodes.hpp | 470 +++++++++++++++++++++++++++++++------------------ main.cpp | 5 +- 8 files changed, 913 insertions(+), 454 deletions(-) create mode 100644 CppEmitter.cpp create mode 100644 CppEmitter.hpp create mode 100644 Emitter.hpp delete mode 100644 Nodes.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6d95090..26332d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,11 +55,16 @@ elseif(BISON_VERSION VERSION_LESS 3.0) message("== Bison 2.5 was found. You have to apply cmake/bison2.patch...") endif() -## 3. Build +## 3. Boost components + +find_package(Boost 1.54 REQUIRED) + +## 4. Build include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} + ${Boost_INCLUDE_DIRS} ) add_definitions(-Wall -Wno-deprecated-register -std=c++0x -DYYDEBUG=0 -O2) @@ -70,6 +75,10 @@ add_flex_bison_dependency(Scanner Parser) add_executable( mcc - main.cpp Nodes.cpp ${BISON_Parser_OUTPUTS} ${FLEX_Scanner_OUTPUTS} + main.cpp + ${BISON_Parser_OUTPUTS} ${FLEX_Scanner_OUTPUTS} + CppEmitter.cpp ) +target_link_libraries(mcc ${Boost_LIBRARIES}) + diff --git a/CppEmitter.cpp b/CppEmitter.cpp new file mode 100644 index 0000000..15ceada --- /dev/null +++ b/CppEmitter.cpp @@ -0,0 +1,381 @@ +/* + * Monicelli: an esoteric language compiler + * + * Copyright (C) 2014 Stefano Sanfilippo + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include "Nodes.hpp" +#include "CppEmitter.hpp" +#include "Pointers.hpp" + +using namespace monicelli; + + +static const std::string STATEMENT_TERMINATOR = ";\n"; +static const std::string BLOCK = " "; +static const int BLOCK_SIZE = 4; + + +void CppEmitter::indent() { + indent_chars += BLOCK_SIZE; +} + +void CppEmitter::dedent() { + indent_chars -= BLOCK_SIZE; +} + +void CppEmitter::emitIndent() { + for (int i = 0; i < indent_chars; ++i) { + stream << BLOCK; + } +} + +void CppEmitter::emit(Program const& program) { + for (Module m: program.getModules()) { + m.emit(this); + stream << "\n"; + } + + if (!program.getModules().empty()) { + stream << "\n"; + } + + for (Function *function: program.getFunctions()) { + emitFunctionSignature(*function); + stream << ";\n"; + } + + if (!program.getFunctions().empty()) { + stream << "\n"; + } + + for (Function *function: program.getFunctions()) { + function->emit(this); + } + + if (program.getMain()) { + program.getMain()->emit(this); + } +} + +void CppEmitter::emitStatements(PointerList const& node) { + for (Statement *s: node) { + s->emit(this); + stream << STATEMENT_TERMINATOR; + } +} + +void CppEmitter::emit(Main const& main) { + stream << "int main() {\n"; + emitStatements(main.getBody()); + stream << "}\n"; +} + +void CppEmitter::emit(Id const& id) { + stream << id.getValue(); +} + +void CppEmitter::emit(Integer const& num) { + stream << num.getValue(); +} + +void CppEmitter::emit(Float const& num) { + stream << num.getValue(); +} + +void CppEmitter::emit(Return const& node) { + stream << "return"; + + if (node.getExpression()) { + stream << ' '; + node.getExpression()->emit(this); + } +} + +void CppEmitter::emit(Print const& node) { + bool needsBraces = + (dynamic_cast(&node.getExpression()) == nullptr) + && + (dynamic_cast(&node.getExpression()) == nullptr) + ; + + stream << "std::cout << "; + if (needsBraces) { + stream << '('; + } + + node.getExpression().emit(this); + + if (needsBraces) { + stream << ')'; + } + stream << " << std::endl"; +} + +void CppEmitter::emit(Input const& node) { + stream << "std::cout << \""; + node.getVariable().emit(this); + stream << "? \";\n"; + stream << "std::cin >> "; + node.getVariable().emit(this); +} + +void CppEmitter::emit(Abort const&) { + stream << "std::exit(1)"; +} + +void CppEmitter::emit(Assert const& node) { + stream << "assert("; + node.getExpression().emit(this); + stream << ")"; +} + +void CppEmitter::emit(Loop const& loop) { + stream << "do {\n"; + emitStatements(loop.getBody()); + stream << "} while ("; + loop.getCondition().emit(this); + stream << ")"; +} + +void CppEmitter::emit(BranchCase const& node) { + node.getCondition().emit(this); + stream << ") {\n"; + emitStatements(node.getBody()); + stream << "}"; +} + +void CppEmitter::emit(Branch const& branch) { + auto &body = branch.getBody(); + auto &var = branch.getVar(); + + stream << "if ("; + var.emit(this); + + if (body.getCases().size() > 0) { + BranchCase *last = body.getCases().back(); + for (BranchCase *cas: body.getCases()) { + cas->emit(this); + if (cas != last) { + stream << " else if ("; + var.emit(this); + } + } + } + + if (!body.getElse()) { + return; + } + + stream << " else {\n"; + emitStatements(*body.getElse()); + stream << "}"; +} + +void CppEmitter::emit(Assignment const& assignment) { + assignment.getName().emit(this); + stream << " = "; + assignment.getValue().emit(this); +} + + +void CppEmitter::emitFunctionArglist(PointerList const& args) { + Expression *last = args.back(); + for (Expression const* arg: args) { + arg->emit(this); + if (arg != last) { + stream << ", "; + } + } +} + + +void CppEmitter::emit(FunctionCall const& funcall) { + funcall.getName().emit(this); + stream << "("; + emitFunctionArglist(funcall.getArgs()); + stream << ")"; +} + +void CppEmitter::emit(Function const& function) { + emitFunctionSignature(function); + stream << " {\n"; + emitStatements(function.getBody()); + stream << "}\n\n"; +} + +std::ostream& operator<<(std::ostream &stream, Type const& type) { + switch (type) { + case Type::INT: + stream << "int"; + break; + case Type::CHAR: + stream << "char"; + break; + case Type::FLOAT: + stream << "float"; + break; + case Type::BOOL: + stream << "bool"; + break; + case Type::DOUBLE: + stream << "double"; + break; + case Type::VOID: + stream << "void"; + break; + } + + return stream; +} + +void CppEmitter::emitFunctionParams(PointerList const& funargs) { + FunArg *last = funargs.back(); + + for (FunArg const* funarg: funargs) { + stream << funarg->getType() << (funarg->isPointer()? "* ": " "); + funarg->getName().emit(this); + if (funarg != last) { + stream << ", "; + } + } +} + +void CppEmitter::emit(Module const& module) { + bool system = (module.getType() == Module::SYSTEM); + stream << "#include " << (system? '<': '"') << module.getName() << (system? '>': '"'); +} + +void CppEmitter::emitFunctionSignature(Function const& function) { + stream << function.getType() << ' '; + function.getName().emit(this); + stream << "("; + emitFunctionParams(function.getArgs()); + stream << ")"; +} + +void CppEmitter::emit(VarDeclaration const& decl) { + stream << decl.getType() << ' '; + if (decl.isPointer()) stream << '*'; + decl.getId().emit(this); + + if (decl.getInitializer()) { + stream << " = "; + decl.getInitializer()->emit(this); + } +} + +void CppEmitter::emitExp(char const* symbol, ExpNode const& node) { + node.getLeft().emit(this); + stream << ' ' << symbol << ' '; + node.getRight().emit(this); +} + +void CppEmitter::emitSemiExp(char const* symbol, SemiExpNode const& node) { + bool braces = (dynamic_cast(&node.getLeft()) == nullptr); + + stream << ' ' << symbol << ' '; + if (braces) stream << "("; + node.getLeft().emit(this); + if (braces) stream << ")"; +} + +void CppEmitter::emit(ExpLt const& node) { + emitExp("<", node); +} + +void CppEmitter::emit(ExpGt const& node) { + emitExp(">", node); +} + +void CppEmitter::emit(ExpLte const& node) { + emitExp("<=", node); +} + +void CppEmitter::emit(ExpGte const& node) { + emitExp(">=", node); +} + +void CppEmitter::emit(ExpPlus const& node) { + emitExp("+", node); +} + +void CppEmitter::emit(ExpMinus const& node) { + emitExp("-", node); +} + +void CppEmitter::emit(ExpTimes const& node) { + emitExp("*", node); +} + +void CppEmitter::emit(ExpDiv const& node) { + emitExp("/", node); +} + +void CppEmitter::emit(ExpShl const& node) { + emitExp("<<", node); +} + +void CppEmitter::emit(ExpShr const& node) { + emitExp(">>", node); +} + +void CppEmitter::emit(SemiExpEq const& node) { + emitSemiExp("==", node); +} + +void CppEmitter::emit(SemiExpLt const& node) { + emitSemiExp("<", node); +} + +void CppEmitter::emit(SemiExpGt const& node) { + emitSemiExp(">", node); +} + +void CppEmitter::emit(SemiExpLte const& node) { + emitSemiExp("<=", node); +} + +void CppEmitter::emit(SemiExpGte const& node) { + emitSemiExp(">=", node); +} + +void CppEmitter::emit(SemiExpPlus const& node) { + emitSemiExp("+", node); +} + +void CppEmitter::emit(SemiExpMinus const& node) { + emitSemiExp("-", node); +} + +void CppEmitter::emit(SemiExpTimes const& node) { + emitSemiExp("*", node); +} + +void CppEmitter::emit(SemiExpDiv const& node) { + emitSemiExp("/", node); +} + +void CppEmitter::emit(SemiExpShl const& node) { + emitSemiExp("<<", node); +} + +void CppEmitter::emit(SemiExpShr const& node) { + emitSemiExp(">>", node); +} + diff --git a/CppEmitter.hpp b/CppEmitter.hpp new file mode 100644 index 0000000..3df8696 --- /dev/null +++ b/CppEmitter.hpp @@ -0,0 +1,93 @@ +#ifndef CPPEMITTER_HPP +#define CPPEMITTER_HPP + +/* + * Monicelli: an esoteric language compiler + * + * Copyright (C) 2014 Stefano Sanfilippo + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "Emitter.hpp" + +#include + + +namespace monicelli { + +class CppEmitter: public Emitter { +public: + CppEmitter(std::ostream *stream): stream(*stream), indent_chars(0) {} + + virtual void emit(Id const&) override; + virtual void emit(Integer const&) override; + virtual void emit(Float const&) override; + virtual void emit(Return const&) override; + virtual void emit(Loop const&) override; + virtual void emit(VarDeclaration const&) override; + virtual void emit(Assignment const&) override; + virtual void emit(Print const&) override; + virtual void emit(Input const&) override; + virtual void emit(Abort const&) override; + virtual void emit(Assert const&) override; + virtual void emit(FunctionCall const&) override; + virtual void emit(BranchCase const&) override; + virtual void emit(Branch const&) override; + virtual void emit(Main const&) override; + virtual void emit(Function const&) override; + virtual void emit(Module const&) override; + virtual void emit(Program const&) override; + virtual void emit(ExpLt const&) override; + virtual void emit(ExpGt const&) override; + virtual void emit(ExpLte const&) override; + virtual void emit(ExpGte const&) override; + virtual void emit(ExpPlus const&) override; + virtual void emit(ExpMinus const&) override; + virtual void emit(ExpTimes const&) override; + virtual void emit(ExpDiv const&) override; + virtual void emit(ExpShl const&) override; + virtual void emit(ExpShr const&) override; + virtual void emit(SemiExpEq const&) override; + virtual void emit(SemiExpLt const&) override; + virtual void emit(SemiExpGt const&) override; + virtual void emit(SemiExpLte const&) override; + virtual void emit(SemiExpGte const&) override; + virtual void emit(SemiExpPlus const&) override; + virtual void emit(SemiExpMinus const&) override; + virtual void emit(SemiExpTimes const&) override; + virtual void emit(SemiExpDiv const&) override; + virtual void emit(SemiExpShl const&) override; + virtual void emit(SemiExpShr const&) override; + +private: + void emitIndent(); + void emitExp(char const* symbol, ExpNode const& node); + void emitSemiExp(char const* symbol, SemiExpNode const& node); + void emitFunctionSignature(Function const& function); + void emitFunctionParams(PointerList const& funargs); + void emitFunctionArglist(PointerList const& args); + void emitStatements(PointerList const& node); + + void indent(); + void dedent(); + + std::ostream &stream; + int indent_chars; +}; + +} + +#endif + diff --git a/Emitter.hpp b/Emitter.hpp new file mode 100644 index 0000000..66d6da3 --- /dev/null +++ b/Emitter.hpp @@ -0,0 +1,113 @@ +#ifndef EMITTER_HPP +#define EMITTER_HPP + +/* + * Monicelli: an esoteric language compiler + * + * Copyright (C) 2014 Stefano Sanfilippo + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +namespace monicelli { + +class Id; +class Number; +class Integer; +class Float; +class Return; +class Loop; +class VarDeclaration; +class Assignment; +class Print; +class Input; +class Abort; +class Assert; +class FunctionCall; +class BranchCase; +class Branch; +class Main; +class Function; +class Module; +class Program; +class ExpLt; +class ExpGt; +class ExpLte; +class ExpGte; +class ExpPlus; +class ExpMinus; +class ExpTimes; +class ExpDiv; +class ExpShl; +class ExpShr; +class SemiExpEq; +class SemiExpLt; +class SemiExpGt; +class SemiExpLte; +class SemiExpGte; +class SemiExpPlus; +class SemiExpMinus; +class SemiExpTimes; +class SemiExpDiv; +class SemiExpShl; +class SemiExpShr; + + +class Emitter { +public: + virtual void emit(Id const&) = 0; + virtual void emit(Integer const&) = 0; + virtual void emit(Float const&) = 0; + virtual void emit(Return const&) = 0; + virtual void emit(Loop const&) = 0; + virtual void emit(VarDeclaration const&) = 0; + virtual void emit(Assignment const&) = 0; + virtual void emit(Print const&) = 0; + virtual void emit(Input const&) = 0; + virtual void emit(Abort const&) = 0; + virtual void emit(Assert const&) = 0; + virtual void emit(FunctionCall const&) = 0; + virtual void emit(BranchCase const&) = 0; + virtual void emit(Branch const&) = 0; + virtual void emit(Main const&) = 0; + virtual void emit(Function const&) = 0; + virtual void emit(Module const&) = 0; + virtual void emit(Program const&) = 0; + virtual void emit(ExpLt const&) = 0; + virtual void emit(ExpGt const&) = 0; + virtual void emit(ExpLte const&) = 0; + virtual void emit(ExpGte const&) = 0; + virtual void emit(ExpPlus const&) = 0; + virtual void emit(ExpMinus const&) = 0; + virtual void emit(ExpTimes const&) = 0; + virtual void emit(ExpDiv const&) = 0; + virtual void emit(ExpShl const&) = 0; + virtual void emit(ExpShr const&) = 0; + virtual void emit(SemiExpEq const&) = 0; + virtual void emit(SemiExpLt const&) = 0; + virtual void emit(SemiExpGt const&) = 0; + virtual void emit(SemiExpLte const&) = 0; + virtual void emit(SemiExpGte const&) = 0; + virtual void emit(SemiExpPlus const&) = 0; + virtual void emit(SemiExpMinus const&) = 0; + virtual void emit(SemiExpTimes const&) = 0; + virtual void emit(SemiExpDiv const&) = 0; + virtual void emit(SemiExpShl const&) = 0; + virtual void emit(SemiExpShr const&) = 0; +}; + +} + +#endif + diff --git a/Monicelli.ypp b/Monicelli.ypp index 07c343c..10d43bd 100644 --- a/Monicelli.ypp +++ b/Monicelli.ypp @@ -78,7 +78,7 @@ bool boolval; Type typeval; Statement* statementval; - StatementList* statlistval; + PointerList* statlistval; Assert* assertval; FunctionCall* callval; Print* printval; @@ -90,16 +90,16 @@ Assignment* assignval; Loop* loopval; BranchCase *caseval; - BranchCaseList *caselistval; + PointerList *caselistval; Return* returnval; Expression* expressionval; - ExpressionList* exprlistval; + PointerList* exprlistval; SemiExpression *semiexpval; Id* idval; Number* numericval; Function* funval; FunArg *argval; - FunArgList *arglistval; + PointerList *arglistval; Main* mainval; } @@ -159,11 +159,16 @@ fun_return: /* epsilon */ { $$ = Type::VOID; } | TYPENAME { $$ = $1; } ; args: - /* epsilon */ { $$ = new FunArgList(); }| PARAMS args_decl { $$ = $2; } + /* epsilon */ { + $$ = new PointerList(); + } + | PARAMS args_decl { + $$ = $2; + } ; args_decl: arg_decl { - $$ = new FunArgList(); + $$ = new PointerList(); $$->push_back($1); } | args_decl COMMA arg_decl { @@ -182,7 +187,7 @@ main: ; statements: /* epsilon */ { - $$ = new StatementList(); + $$ = new PointerList(); } | statements statement { if ($2 != nullptr) { @@ -271,7 +276,7 @@ branch_body: ; cases: case_stmt { - $$ = new BranchCaseList(); + $$ = new PointerList(); $$->push_back($1); } | cases CASE_END case_stmt { @@ -291,7 +296,7 @@ fun_call: ; call_args: /* epsilon */ { - $$ = new ExpressionList(); + $$ = new PointerList(); } | PARAMS call_arglist { $$ = $2; @@ -299,7 +304,7 @@ call_args: ; call_arglist: expression { - $$ = new ExpressionList(); + $$ = new PointerList(); $$->push_back($1); } | call_arglist COMMA expression { diff --git a/Nodes.cpp b/Nodes.cpp deleted file mode 100644 index a499221..0000000 --- a/Nodes.cpp +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Monicelli: an esoteric language compiler - * - * Copyright (C) 2014 Stefano Sanfilippo - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "Nodes.hpp" - -using namespace monicelli; - -static const std::string BLOCK = " "; - -std::ostream& monicelli::operator<<(std::ostream &stream, const Type &type) { - switch (type) { - case Type::INT: - stream << "int"; - break; - case Type::CHAR: - stream << "char"; - break; - case Type::FLOAT: - stream << "float"; - break; - case Type::BOOL: - stream << "bool"; - break; - case Type::DOUBLE: - stream << "double"; - break; - case Type::VOID: - stream << "void"; - break; - } - - return stream; -} - -void emitIndent(std::ostream &stream, int indent) { - for (int i = 0; i < indent; ++i) { - stream << BLOCK; - } -} - -void Id::emit(std::ostream &stream, int indent) { - stream << *value; -} - -void Integer::emit(std::ostream &stream, int indent) { - stream << value; -} - -void Float::emit(std::ostream &stream, int indent) { - stream << value; -} - -void ExpNode::emit(std::ostream &stream, int indent) { - left->emit(stream); - stream << ' ' << getSym() << ' '; - right->emit(stream); -} - -void SemiExpNode::emit(std::ostream &stream, int indent) { - SimpleExpression *e = dynamic_cast(left.get()); - bool braces = (e == nullptr); - - stream << ' ' << getSym() << ' '; - if (braces) stream << "("; - left->emit(stream); - if (braces) stream << ")"; -} - -void StatementList::emit(std::ostream &stream, int indent) { - for (Statement *s: *this) { - emitIndent(stream, indent); - s->emit(stream, indent); - stream << ";\n"; - } -} - -void Return::emit(std::ostream &stream, int indent) { - stream << "return"; - - if (expression != nullptr) { - stream << ' '; - expression->emit(stream); - } -} - -void Loop::emit(std::ostream &stream, int indent) { - stream << "do {\n"; - - body->emit(stream, indent + 1); - - emitIndent(stream, indent); - stream << "} while ("; - condition->emit(stream); - stream << ")"; -} - -void BranchCase::emit(std::ostream &stream, int indent) { - condition->emit(stream); - stream << ") {\n"; - body->emit(stream, indent); - emitIndent(stream, indent - 1); - stream << "}"; -} - -void Branch::emit(std::ostream &stream, int indent) { - stream << "if ("; - var->emit(stream); - - if (body->cases->size() > 0) { - BranchCase *last = body->cases->back(); - for (BranchCase *c: *body->cases) { - c->emit(stream, indent + 1); - if (c != last) { - stream << " else if ("; - var->emit(stream); - } - } - } - - if (body->els == nullptr) { - return; - } - - stream << " else {\n"; - body->els->emit(stream, indent + 1); - emitIndent(stream, indent); - stream << "}"; -} - -void VarDeclaration::emit(std::ostream &stream, int indent) { - stream << type << ' '; - if (point) stream << '*'; - name->emit(stream); - - if (init != nullptr) { - stream << " = "; - init->emit(stream); - } -} - -void Assignment::emit(std::ostream &stream, int indent) { - name->emit(stream); - stream << " = "; - value->emit(stream); -} - -void Print::emit(std::ostream &stream, int indent) { - bool simpleExpression = (dynamic_cast(expression.get()) != nullptr); - - stream << "std::cout << "; - if (!simpleExpression) { - stream << '('; - } - - expression->emit(stream); - - if (!simpleExpression) { - stream << ')'; - } - stream << " << std::endl"; -} - -void Input::emit(std::ostream &stream, int indent) { - stream << "std::cout << \""; - variable->emit(stream); - stream << "? \";\n"; - emitIndent(stream, indent); - stream << "std::cin >> "; - variable->emit(stream); -} - -void Abort::emit(std::ostream &stream, int indent) { - stream << "std::exit(1)"; -} - -void Assert::emit(std::ostream &stream, int indent) { - stream << "assert("; - expression->emit(stream); - stream << ")"; -} - -void FunctionCall::emit(std::ostream &stream, int indent) { - name->emit(stream); - stream << "("; - args->emit(stream); - stream << ")"; -} - -void FunArg::emit(std::ostream &stream, int indent) { - stream << type << (pointer? "* ": " "); - name->emit(stream); -} - -void Function::emit(std::ostream &stream, int indent) { - emitSignature(stream, indent); - stream << " {\n"; - body->emit(stream, indent + 1); - stream << "}\n\n"; -} - -void Function::emitSignature(std::ostream &stream, int indent) { - emitIndent(stream, indent); - - stream << type << ' '; - name->emit(stream); - stream << "("; - args->emit(stream); - stream << ")"; -} - -void Module::emit(std::ostream &stream, int indent) { - bool system = (type == Module::SYSTEM); - stream << "#include " << (system? '<': '"') << name << (system? '>': '"'); -} - -void Main::emit(std::ostream &stream, int indent) { - emitIndent(stream, indent); - - stream << "int main() {\n"; - body->emit(stream, indent + 1); - stream << "}\n"; -} - -void Program::emit(std::ostream &stream, int indent) { - for (Module m: modules) { - m.emit(stream); - stream << "\n"; - } - - if (!modules.empty()) { - stream << "\n"; - } - - for (Function *f: functions) { - f->emitSignature(stream); - stream << ";\n"; - } - - if (!functions.empty()) { - stream << "\n"; - } - - for (Function *f: functions) { - f->emit(stream); - } - - if (main != nullptr) { - main->emit(stream); - } -} - diff --git a/Nodes.hpp b/Nodes.hpp index c794803..b6c93e1 100644 --- a/Nodes.hpp +++ b/Nodes.hpp @@ -1,5 +1,5 @@ -#ifndef NODES_H -#define NODES_H +#ifndef NODES_HPP +#define NODES_HPP /* * Monicelli: an esoteric language compiler @@ -20,10 +20,15 @@ * along with this program. If not, see . */ +#include "Emitter.hpp" #include "Pointers.hpp" #include #include +#include + +#define maybe_return(val) \ + if ((val) != nullptr) return *(val); else return boost::none; namespace monicelli { @@ -36,99 +41,66 @@ enum class Type { VOID }; -std::ostream& operator<<(std::ostream &stream, const Type &type); - - class Emittable { public: - virtual void emit(std::ostream &stream, int indent = 0) = 0; + virtual ~Emittable() {} + virtual void emit(Emitter *emitter) const = 0; }; class Statement: public Emittable { public: - virtual ~Statement() {} + virtual void emit(Emitter *) const {} }; - class SemiExpression: public Emittable { public: - virtual ~SemiExpression() {} + virtual void emit(Emitter *) const {} }; - class Expression: public Emittable { public: - virtual ~Expression() {} + virtual void emit(Emitter *) const {} }; -public: -}; - - -class StatementList: public PointerList, public Emittable { -public: - virtual void emit(std::ostream &stream, int indent = 0); -}; - - -template -class ListEmittable: public PointerList, public Emittable { -public: - virtual void emit(std::ostream &stream, int indent = 0) { - if (this->size() > 0) { - T *last = this->back(); // TODO wut? - for (T *e: *this) { - e->emit(stream); - if (e != last) { - stream << getSeparator(); - } - } - } - } - -protected: - virtual std::string getSeparator() const { - return ", "; - } -}; - - -class ExpressionList: public ListEmittable { -}; - - class SimpleExpression: public Expression { +public: + virtual void emit(Emitter *) const {} }; class Id: public SimpleExpression { public: explicit Id(std::string *c): value(c) {} - virtual ~Id() {} - virtual void emit(std::ostream &stream, int indent = 0); + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); + } + + std::string const& getValue() const { + return *value; + } private: Pointer value; }; -class IdList: public ListEmittable { -}; - - -class Number: public SimpleExpression { -public: - virtual void emit(std::ostream &stream, int indent = 0) {} -}; +class Number: public SimpleExpression {}; class Integer: public Number { public: Integer(long i): value(i) {} - virtual void emit(std::ostream &stream, int indent = 0); + + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); + } + + long getValue() const { + return value; + } private: long value; @@ -138,7 +110,14 @@ private: class Float: public Number { public: Float(double f): value(f) {} - virtual void emit(std::ostream &stream, int indent = 0); + + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); + } + + double getValue() const { + return value; + } private: double value; @@ -148,7 +127,14 @@ private: class Return: public Statement { public: explicit Return(Expression *e): expression(e) {} - virtual void emit(std::ostream &stream, int indent = 0); + + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); + } + + boost::optional getExpression() const { + maybe_return(expression); + } private: Pointer expression; @@ -157,11 +143,22 @@ private: class Loop: public Statement { public: - Loop(StatementList *b, Expression *c): body(b), condition(c) {} - virtual void emit(std::ostream &stream, int indent = 0); + Loop(PointerList *b, Expression *c): body(b), condition(c) {} + + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); + } + + PointerList const& getBody() const { + return *body; + } + + Expression const& getCondition() const { + return *condition; + } private: - Pointer body; + Pointer> body; Pointer condition; }; @@ -170,7 +167,26 @@ class VarDeclaration: public Statement { public: VarDeclaration(Id *n, Type t, bool p, Expression *i): name(n), point(p), init(i), type(t) {} - virtual void emit(std::ostream &stream, int indent = 0); + + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); + } + + Id const& getId() const { + return *name; + } + + bool isPointer() const { + return point; + } + + boost::optional getInitializer() const { + maybe_return(init); + } + + Type getType() const { + return type; + } private: Pointer name; @@ -183,7 +199,18 @@ private: class Assignment: public Statement { public: Assignment(Id *n, Expression *v): name(n), value(v) {} - virtual void emit(std::ostream &stream, int indent = 0); + + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); + } + + Id const& getName() const { + return *name; + } + + Expression const& getValue() const { + return *value; + } private: Pointer name; @@ -194,7 +221,14 @@ private: class Print: public Statement { public: explicit Print(Expression *e): expression(e) {} - virtual void emit(std::ostream &stream, int indent = 0); + + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); + } + + Expression const& getExpression() const { + return *expression; + } private: Pointer expression; @@ -204,7 +238,14 @@ private: class Input: public Statement { public: explicit Input(Id *v): variable(v) {} - virtual void emit(std::ostream &stream, int indent = 0); + + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); + } + + Id const& getVariable() const { + return *variable; + } private: Pointer variable; @@ -213,14 +254,23 @@ private: class Abort: public Statement { public: - virtual void emit(std::ostream &stream, int indent = 0); + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); + } }; class Assert: public Statement { public: explicit Assert(Expression *e): expression(e) {} - virtual void emit(std::ostream &stream, int indent = 0); + + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); + } + + Expression const& getExpression() const { + return *expression; + } private: Pointer expression; @@ -229,45 +279,80 @@ private: class FunctionCall: public Statement, public Expression { public: - FunctionCall(Id *n, ExpressionList *a): name(n), args(a) {} - virtual void emit(std::ostream &stream, int indent = 0); + FunctionCall(Id *n, PointerList *a): name(n), args(a) {} + + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); + } + + Id const& getName() const { + return *name; + } + + PointerList const& getArgs() const { + return *args; + } private: Pointer name; - Pointer args; + Pointer> args; }; class BranchCase: public Emittable { public: - BranchCase(SemiExpression *c, StatementList *b): condition(c), body(b) {} - virtual ~BranchCase() {} + BranchCase(SemiExpression *c, PointerList *b): condition(c), body(b) {} + + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); + } + + SemiExpression const& getCondition() const { + return *condition; + } + + PointerList const& getBody() const { + return *body; + } - virtual void emit(std::ostream &stream, int indent = 0); private: Pointer condition; - Pointer body; + Pointer> body; }; -typedef PointerList BranchCaseList; - - class Branch: public Statement { public: - struct Body { + class Body { public: - Body(BranchCaseList *c, StatementList *e = nullptr): cases(c), els(e) {} + Body(PointerList *c, PointerList *e = nullptr): cases(c), els(e) {} + + PointerList const& getCases() const { + return *cases; + } + + boost::optional const&> getElse() const { + maybe_return(els); + } private: - Pointer cases; - Pointer els; - - friend class Branch; + Pointer> cases; + Pointer> els; }; Branch(Id *v, Branch::Body *b): var(v), body(b) {} - virtual void emit(std::ostream &stream, int indent = 0); + + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); + } + + Id const& getVar() const { + return *var; + } + + Branch::Body const& getBody() const { + return *body; + } private: Pointer var; @@ -277,20 +362,36 @@ private: class Main: public Emittable { public: - Main(StatementList *s): body(s) {} - virtual void emit(std::ostream &stream, int indent = 0); + Main(PointerList *s): body(s) {} + + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); + } + + PointerList const& getBody() const { + return *body; + } private: - Pointer body; + Pointer> body; }; -class FunArg: public Emittable { +class FunArg { public: FunArg(Id *n, Type t, bool p): name(n), type(t), pointer(p) {} - virtual ~FunArg() {} - virtual void emit(std::ostream &stream, int indent = 0); + Id const& getName() const { + return *name; + } + + Type getType() const { + return type; + } + + bool isPointer() const { + return pointer; + } private: Pointer name; @@ -299,23 +400,36 @@ private: }; -typedef ListEmittable FunArgList; - - class Function: public Emittable { public: - Function(Id *n, Type r, FunArgList *a, StatementList *b): + Function(Id *n, Type r, PointerList *a, PointerList *b): name(n), type(r), args(a), body(b) {} - virtual ~Function() {} - virtual void emit(std::ostream &stream, int indent = 0); - void emitSignature(std::ostream &stream, int indent = 0); + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); + } + + Id const& getName() const { + return *name; + } + + Type getType() const { + return type; + } + + PointerList const& getArgs() const { + return *args; + } + + PointerList const& getBody() const { + return *body; + } private: Pointer name; Type type; - Pointer args; - Pointer body; + Pointer> args; + Pointer> body; }; @@ -326,7 +440,10 @@ public: }; Module(const std::string &n, Type s): name(n), type(s) {} - virtual ~Module() {} + + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); + } bool operator==(const Module &other) const noexcept { return (name == other.name) && (type == other.type); @@ -336,7 +453,13 @@ public: return std::hash()(name) ^ std::hash()(type); } - virtual void emit(std::ostream &stream, int indent = 0); + std::string const& getName() const { + return name; + } + + Type getType() const { + return type; + } private: std::string name; @@ -348,7 +471,7 @@ private: namespace std { template<> -class hash { +struct hash { public: size_t operator ()(const monicelli::Module &e) const noexcept { return e.hash(); @@ -361,7 +484,9 @@ namespace monicelli { class Program: public Emittable { public: - virtual void emit(std::ostream &stream, int indent = 0); + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); + } void setMain(Main *m) { main = Pointer
(m); @@ -376,6 +501,18 @@ public: delete m; } + boost::optional
getMain() const { + maybe_return(main); + } + + PointerList const& getFunctions() const { + return functions; + } + + std::unordered_set const& getModules() const { + return modules; + } + private: Pointer
main; PointerList functions; @@ -386,10 +523,14 @@ private: class ExpNode: public Expression { public: ExpNode(Expression *l, Expression *r): left(l), right(r) {} - virtual void emit(std::ostream &stream, int indent = 0); -protected: - virtual std::string getSym() = 0; + Expression const& getLeft() const { + return *left; + } + + Expression const& getRight() const { + return *right; + } private: Pointer left; @@ -401,9 +542,8 @@ class ExpLt: public ExpNode { public: ExpLt(Expression *l, Expression *r): ExpNode(l, r) {} -protected: - virtual std::string getSym() { - return "<"; + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); } }; @@ -412,9 +552,8 @@ class ExpGt: public ExpNode { public: ExpGt(Expression *l, Expression *r): ExpNode(l, r) {} -protected: - virtual std::string getSym() { - return ">"; + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); } }; @@ -423,9 +562,8 @@ class ExpLte: public ExpNode { public: ExpLte(Expression *l, Expression *r): ExpNode(l, r) {} -protected: - virtual std::string getSym() { - return "<="; + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); } }; @@ -434,9 +572,8 @@ class ExpGte: public ExpNode { public: ExpGte(Expression *l, Expression *r): ExpNode(l, r) {} -protected: - virtual std::string getSym() { - return ">="; + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); } }; @@ -445,9 +582,8 @@ class ExpPlus: public ExpNode { public: ExpPlus(Expression *l, Expression *r): ExpNode(l, r) {} -protected: - virtual std::string getSym() { - return "+"; + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); } }; @@ -456,9 +592,8 @@ class ExpMinus: public ExpNode { public: ExpMinus(Expression *l, Expression *r): ExpNode(l, r) {} -protected: - virtual std::string getSym() { - return "-"; + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); } }; @@ -467,9 +602,8 @@ class ExpTimes: public ExpNode { public: ExpTimes(Expression *l, Expression *r): ExpNode(l, r) {} -protected: - virtual std::string getSym() { - return "*"; + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); } }; @@ -478,9 +612,8 @@ class ExpDiv: public ExpNode { public: ExpDiv(Expression *l, Expression *r): ExpNode(l, r) {} -protected: - virtual std::string getSym() { - return "/"; + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); } }; @@ -489,9 +622,8 @@ class ExpShl: public ExpNode { public: ExpShl(Expression *l, Expression *r): ExpNode(l, r) {} -protected: - virtual std::string getSym() { - return "<<"; + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); } }; @@ -500,9 +632,8 @@ class ExpShr: public ExpNode { public: ExpShr(Expression *l, Expression *r): ExpNode(l, r) {} -protected: - virtual std::string getSym() { - return ">>"; + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); } }; @@ -510,10 +641,10 @@ protected: class SemiExpNode: public SemiExpression { public: SemiExpNode(Expression *l): left(l) {} - virtual void emit(std::ostream &stream, int indent = 0); -protected: - virtual std::string getSym() = 0; + Expression const& getLeft() const { + return *left; + } private: Pointer left; @@ -525,9 +656,8 @@ class SemiExpEq: public SemiExpNode { public: SemiExpEq(Expression *l): SemiExpNode(l) {} -protected: - virtual std::string getSym() { - return "=="; + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); } }; @@ -536,9 +666,8 @@ class SemiExpLt: public SemiExpNode { public: SemiExpLt(Expression *l): SemiExpNode(l) {} -protected: - virtual std::string getSym() { - return "<"; + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); } }; @@ -547,9 +676,8 @@ class SemiExpGt: public SemiExpNode { public: SemiExpGt(Expression *l): SemiExpNode(l) {} -protected: - virtual std::string getSym() { - return ">"; + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); } }; @@ -558,9 +686,8 @@ class SemiExpLte: public SemiExpNode { public: SemiExpLte(Expression *l): SemiExpNode(l) {} -protected: - virtual std::string getSym() { - return "<="; + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); } }; @@ -569,9 +696,8 @@ class SemiExpGte: public SemiExpNode { public: SemiExpGte(Expression *l): SemiExpNode(l) {} -protected: - virtual std::string getSym() { - return ">="; + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); } }; @@ -580,9 +706,8 @@ class SemiExpPlus: public SemiExpNode { public: SemiExpPlus(Expression *l): SemiExpNode(l) {} -protected: - virtual std::string getSym() { - return "+"; + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); } }; @@ -591,9 +716,8 @@ class SemiExpMinus: public SemiExpNode { public: SemiExpMinus(Expression *l): SemiExpNode(l) {} -protected: - virtual std::string getSym() { - return "-"; + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); } }; @@ -602,9 +726,8 @@ class SemiExpTimes: public SemiExpNode { public: SemiExpTimes(Expression *l): SemiExpNode(l) {} -protected: - virtual std::string getSym() { - return "*"; + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); } }; @@ -613,9 +736,8 @@ class SemiExpDiv: public SemiExpNode { public: SemiExpDiv(Expression *l): SemiExpNode(l) {} -protected: - virtual std::string getSym() { - return "/"; + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); } }; @@ -624,9 +746,8 @@ class SemiExpShl: public SemiExpNode { public: SemiExpShl(Expression *l): SemiExpNode(l) {} -protected: - virtual std::string getSym() { - return "<<"; + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); } }; @@ -635,13 +756,14 @@ class SemiExpShr: public SemiExpNode { public: SemiExpShr(Expression *l): SemiExpNode(l) {} -protected: - virtual std::string getSym() { - return ">>"; + virtual void emit(Emitter *emitter) const { + emitter->emit(*this); } }; } // namespace +#undef maybe_return + #endif diff --git a/main.cpp b/main.cpp index 5a54e2a..70ef9e8 100644 --- a/main.cpp +++ b/main.cpp @@ -19,6 +19,7 @@ #include "Scanner.hpp" #include "Parser.hpp" +#include "CppEmitter.hpp" #include #include @@ -35,7 +36,9 @@ int main(int argc, char **argv) { #endif parser.parse(); - program.emit(std::cout); + CppEmitter emitter(&std::cout); + + program.emit(&emitter); return 0; }