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.
This commit is contained in:
Stefano Sanfilippo 2015-03-05 01:16:40 +01:00
parent 0fb3ea5dd6
commit b0a01d2fb7
8 changed files with 913 additions and 454 deletions

View File

@ -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})

381
CppEmitter.cpp Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include <string>
#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<Statement> 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<SimpleExpression const*>(&node.getExpression()) == nullptr)
&&
(dynamic_cast<FunctionCall const*>(&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<Expression> 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<FunArg> 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<SimpleExpression const*>(&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);
}

93
CppEmitter.hpp Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include "Emitter.hpp"
#include <iostream>
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<FunArg> const& funargs);
void emitFunctionArglist(PointerList<Expression> const& args);
void emitStatements(PointerList<Statement> const& node);
void indent();
void dedent();
std::ostream &stream;
int indent_chars;
};
}
#endif

113
Emitter.hpp Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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

View File

@ -78,7 +78,7 @@
bool boolval;
Type typeval;
Statement* statementval;
StatementList* statlistval;
PointerList<Statement>* statlistval;
Assert* assertval;
FunctionCall* callval;
Print* printval;
@ -90,16 +90,16 @@
Assignment* assignval;
Loop* loopval;
BranchCase *caseval;
BranchCaseList *caselistval;
PointerList<BranchCase> *caselistval;
Return* returnval;
Expression* expressionval;
ExpressionList* exprlistval;
PointerList<Expression>* exprlistval;
SemiExpression *semiexpval;
Id* idval;
Number* numericval;
Function* funval;
FunArg *argval;
FunArgList *arglistval;
PointerList<FunArg> *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<FunArg>();
}
| PARAMS args_decl {
$$ = $2;
}
;
args_decl:
arg_decl {
$$ = new FunArgList();
$$ = new PointerList<FunArg>();
$$->push_back($1);
}
| args_decl COMMA arg_decl {
@ -182,7 +187,7 @@ main:
;
statements:
/* epsilon */ {
$$ = new StatementList();
$$ = new PointerList<Statement>();
}
| statements statement {
if ($2 != nullptr) {
@ -271,7 +276,7 @@ branch_body:
;
cases:
case_stmt {
$$ = new BranchCaseList();
$$ = new PointerList<BranchCase>();
$$->push_back($1);
}
| cases CASE_END case_stmt {
@ -291,7 +296,7 @@ fun_call:
;
call_args:
/* epsilon */ {
$$ = new ExpressionList();
$$ = new PointerList<Expression>();
}
| PARAMS call_arglist {
$$ = $2;
@ -299,7 +304,7 @@ call_args:
;
call_arglist:
expression {
$$ = new ExpressionList();
$$ = new PointerList<Expression>();
$$->push_back($1);
}
| call_arglist COMMA expression {

267
Nodes.cpp
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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<SimpleExpression*>(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<SimpleExpression*>(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);
}
}

470
Nodes.hpp
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include "Emitter.hpp"
#include "Pointers.hpp"
#include <functional>
#include <unordered_set>
#include <boost/optional.hpp>
#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<Statement>, public Emittable {
public:
virtual void emit(std::ostream &stream, int indent = 0);
};
template <class T>
class ListEmittable: public PointerList<T>, 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<Expression> {
};
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<std::string> value;
};
class IdList: public ListEmittable<Id> {
};
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<Expression const&> getExpression() const {
maybe_return(expression);
}
private:
Pointer<Expression> 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<Statement> *b, Expression *c): body(b), condition(c) {}
virtual void emit(Emitter *emitter) const {
emitter->emit(*this);
}
PointerList<Statement> const& getBody() const {
return *body;
}
Expression const& getCondition() const {
return *condition;
}
private:
Pointer<StatementList> body;
Pointer<PointerList<Statement>> body;
Pointer<Expression> 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<Expression const&> getInitializer() const {
maybe_return(init);
}
Type getType() const {
return type;
}
private:
Pointer<Id> 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<Id> 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> 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<Id> 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> 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<Expression> *a): name(n), args(a) {}
virtual void emit(Emitter *emitter) const {
emitter->emit(*this);
}
Id const& getName() const {
return *name;
}
PointerList<Expression> const& getArgs() const {
return *args;
}
private:
Pointer<Id> name;
Pointer<ExpressionList> args;
Pointer<PointerList<Expression>> args;
};
class BranchCase: public Emittable {
public:
BranchCase(SemiExpression *c, StatementList *b): condition(c), body(b) {}
virtual ~BranchCase() {}
BranchCase(SemiExpression *c, PointerList<Statement> *b): condition(c), body(b) {}
virtual void emit(Emitter *emitter) const {
emitter->emit(*this);
}
SemiExpression const& getCondition() const {
return *condition;
}
PointerList<Statement> const& getBody() const {
return *body;
}
virtual void emit(std::ostream &stream, int indent = 0);
private:
Pointer<SemiExpression> condition;
Pointer<StatementList> body;
Pointer<PointerList<Statement>> body;
};
typedef PointerList<BranchCase> BranchCaseList;
class Branch: public Statement {
public:
struct Body {
class Body {
public:
Body(BranchCaseList *c, StatementList *e = nullptr): cases(c), els(e) {}
Body(PointerList<BranchCase> *c, PointerList<Statement> *e = nullptr): cases(c), els(e) {}
PointerList<BranchCase> const& getCases() const {
return *cases;
}
boost::optional<PointerList<Statement> const&> getElse() const {
maybe_return(els);
}
private:
Pointer<BranchCaseList> cases;
Pointer<StatementList> els;
friend class Branch;
Pointer<PointerList<BranchCase>> cases;
Pointer<PointerList<Statement>> 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<Id> 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<Statement> *s): body(s) {}
virtual void emit(Emitter *emitter) const {
emitter->emit(*this);
}
PointerList<Statement> const& getBody() const {
return *body;
}
private:
Pointer<StatementList> body;
Pointer<PointerList<Statement>> 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<Id> name;
@ -299,23 +400,36 @@ private:
};
typedef ListEmittable<FunArg> FunArgList;
class Function: public Emittable {
public:
Function(Id *n, Type r, FunArgList *a, StatementList *b):
Function(Id *n, Type r, PointerList<FunArg> *a, PointerList<Statement> *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<FunArg> const& getArgs() const {
return *args;
}
PointerList<Statement> const& getBody() const {
return *body;
}
private:
Pointer<Id> name;
Type type;
Pointer<FunArgList> args;
Pointer<StatementList> body;
Pointer<PointerList<FunArg>> args;
Pointer<PointerList<Statement>> 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<std::string>()(name) ^ std::hash<bool>()(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<monicelli::Module> {
struct hash<monicelli::Module> {
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<Main>(m);
@ -376,6 +501,18 @@ public:
delete m;
}
boost::optional<Main const&> getMain() const {
maybe_return(main);
}
PointerList<Function> const& getFunctions() const {
return functions;
}
std::unordered_set<Module> const& getModules() const {
return modules;
}
private:
Pointer<Main> main;
PointerList<Function> 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<Expression> 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<Expression> 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

View File

@ -19,6 +19,7 @@
#include "Scanner.hpp"
#include "Parser.hpp"
#include "CppEmitter.hpp"
#include <iostream>
#include <fstream>
@ -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;
}