Implementing error handling in emitters.

As a result, Emitter iface changes by providing a bool retval.
False means failure and should be managed as such.
This commit is contained in:
Stefano Sanfilippo 2015-03-06 14:29:52 +01:00
parent 2ce76a1dfd
commit b7be4dc37f
6 changed files with 312 additions and 198 deletions

View File

@ -29,6 +29,14 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <unordered_set>
#include <initializer_list>
//TODO remove
#include <iostream>
// Yes, that's right, no ending ;
#define GUARDED(call) if (!(call)) return false
using namespace monicelli; using namespace monicelli;
@ -75,6 +83,16 @@ llvm::Value* isTrue(llvm::IRBuilder<> &builder, llvm::Value* test, llvm::Twine c
); );
} }
static
bool reportError(std::initializer_list<std::string> const& what) {
for (std::string const& chunk: what) {
std::cerr << chunk << ' ';
}
std::cerr << std::endl;
return false;
}
BitcodeEmitter::BitcodeEmitter() { BitcodeEmitter::BitcodeEmitter() {
module = std::unique_ptr<llvm::Module>(new llvm::Module("monicelli", getGlobalContext())); module = std::unique_ptr<llvm::Module>(new llvm::Module("monicelli", getGlobalContext()));
d = new Private; d = new Private;
@ -84,16 +102,18 @@ BitcodeEmitter::~BitcodeEmitter() {
delete d; delete d;
} }
void BitcodeEmitter::emit(Return const& node) { bool BitcodeEmitter::emit(Return const& node) {
if (node.getExpression()) { if (node.getExpression()) {
node.getExpression()->emit(this); GUARDED(node.getExpression()->emit(this));
d->builder.CreateRet(d->retval); d->builder.CreateRet(d->retval);
} else { } else {
d->builder.CreateRetVoid(); d->builder.CreateRetVoid();
} }
return true;
} }
void BitcodeEmitter::emit(Loop const& node) { bool BitcodeEmitter::emit(Loop const& node) {
llvm::Function *father = d->builder.GetInsertBlock()->getParent(); llvm::Function *father = d->builder.GetInsertBlock()->getParent();
llvm::BasicBlock *body = llvm::BasicBlock::Create( llvm::BasicBlock *body = llvm::BasicBlock::Create(
@ -105,11 +125,11 @@ void BitcodeEmitter::emit(Loop const& node) {
d->scope.enter(); d->scope.enter();
for (Statement const* statement: node.getBody()) { for (Statement const* statement: node.getBody()) {
statement->emit(this); GUARDED(statement->emit(this));
} }
d->scope.leave(); d->scope.leave();
node.getCondition().emit(this); GUARDED(node.getCondition().emit(this));
llvm::Value *loopTest = isTrue(d->builder, d->retval, "looptest"); llvm::Value *loopTest = isTrue(d->builder, d->retval, "looptest");
@ -119,68 +139,88 @@ void BitcodeEmitter::emit(Loop const& node) {
d->builder.CreateCondBr(loopTest, body, after); d->builder.CreateCondBr(loopTest, body, after);
d->builder.SetInsertPoint(after); d->builder.SetInsertPoint(after);
return true;
} }
void BitcodeEmitter::emit(VarDeclaration const& node) { bool BitcodeEmitter::emit(VarDeclaration const& node) {
llvm::Function *father = d->builder.GetInsertBlock()->getParent(); llvm::Function *father = d->builder.GetInsertBlock()->getParent();
llvm::AllocaInst *alloc = allocateVar( llvm::AllocaInst *alloc = allocateVar(
father, node.getId(), LLVMType(node.getType()) father, node.getId(), LLVMType(node.getType())
); );
if (node.getInitializer()) { if (node.getInitializer()) {
node.getInitializer()->emit(this); GUARDED(node.getInitializer()->emit(this));
d->builder.CreateStore(d->retval, alloc); d->builder.CreateStore(d->retval, alloc);
} }
// TODO pointers // TODO pointers
d->scope.push(node.getId().getValue(), alloc); d->scope.push(node.getId().getValue(), alloc);
return true;
} }
void BitcodeEmitter::emit(Assignment const& node) { bool BitcodeEmitter::emit(Assignment const& node) {
node.getValue().emit(this); GUARDED(node.getValue().emit(this));
auto var = d->scope.lookup(node.getName().getValue()); auto var = d->scope.lookup(node.getName().getValue());
if (!var) { if (!var) {
// TODO undefined var return reportError({
"Attempting assignment to undefined var", node.getName().getValue()
});
} }
d->builder.CreateStore(d->retval, *var); d->builder.CreateStore(d->retval, *var);
return true;
} }
void BitcodeEmitter::emit(Print const& node) { bool BitcodeEmitter::emit(Print const& node) {
return true;
} }
void BitcodeEmitter::emit(Input const& node) { bool BitcodeEmitter::emit(Input const& node) {
return true;
} }
void BitcodeEmitter::emit(Abort const& node) { bool BitcodeEmitter::emit(Abort const& node) {
return true;
} }
void BitcodeEmitter::emit(Assert const& node) { bool BitcodeEmitter::emit(Assert const& node) {
return true;
} }
void BitcodeEmitter::emit(FunctionCall const& node) { bool BitcodeEmitter::emit(FunctionCall const& node) {
llvm::Function *callee = module->getFunction(node.getName().getValue()); llvm::Function *callee = module->getFunction(node.getName().getValue());
if (callee == 0) { if (callee == 0) {
// TODO Error return reportError({
"Attempting to call undefined function", node.getName().getValue()
});
} }
if (callee->arg_size() != node.getArgs().size()) { if (callee->arg_size() != node.getArgs().size()) {
// TODO Error return reportError({
"Argument number mismatch, expected",
std::to_string(callee->arg_size()),
"given", std::to_string(node.getArgs().size())
});
} }
std::vector<llvm::Value*> callargs; std::vector<llvm::Value*> callargs;
for (Expression const* arg: node.getArgs()) { for (Expression const* arg: node.getArgs()) {
arg->emit(this); GUARDED(arg->emit(this));
callargs.push_back(d->retval); callargs.push_back(d->retval);
} }
d->retval = d->builder.CreateCall(callee, callargs); d->retval = d->builder.CreateCall(callee, callargs);
return true;
} }
void BitcodeEmitter::emit(Branch const& node) { bool BitcodeEmitter::emit(Branch const& node) {
Branch::Body const& body = node.getBody(); Branch::Body const& body = node.getBody();
llvm::Function *func = d->builder.GetInsertBlock()->getParent(); llvm::Function *func = d->builder.GetInsertBlock()->getParent();
@ -204,7 +244,7 @@ void BitcodeEmitter::emit(Branch const& node) {
d->builder.SetInsertPoint(thenbb); d->builder.SetInsertPoint(thenbb);
d->scope.enter(); d->scope.enter();
for (Statement const* statement: cas->getBody()) { for (Statement const* statement: cas->getBody()) {
statement->emit(this); GUARDED(statement->emit(this));
} }
d->scope.leave(); d->scope.leave();
d->builder.CreateBr(mergebb); d->builder.CreateBr(mergebb);
@ -221,7 +261,7 @@ void BitcodeEmitter::emit(Branch const& node) {
if (body.getElse()) { if (body.getElse()) {
d->scope.enter(); d->scope.enter();
for (Statement const* statement: *body.getElse()) { for (Statement const* statement: *body.getElse()) {
statement->emit(this); GUARDED(statement->emit(this));
} }
d->scope.leave(); d->scope.leave();
d->builder.CreateBr(mergebb); d->builder.CreateBr(mergebb);
@ -229,19 +269,33 @@ void BitcodeEmitter::emit(Branch const& node) {
func->getBasicBlockList().push_back(mergebb); func->getBasicBlockList().push_back(mergebb);
d->builder.SetInsertPoint(mergebb); d->builder.SetInsertPoint(mergebb);
return true;
} }
void BitcodeEmitter::emit(Function const& node) { bool BitcodeEmitter::emit(Function const& node) {
d->scope.enter(); d->scope.enter();
std::vector<llvm::Type*> argtypes; std::vector<llvm::Type*> argTypes;
for (FunArg const* arg: node.getArgs()) { for (FunArg const* arg: node.getArgs()) {
argtypes.emplace_back(LLVMType(arg->getType())); argTypes.emplace_back(LLVMType(arg->getType()));
}
std::unordered_set<std::string> argsSet;
for (FunArg const* arg: node.getArgs()) {
std::string const& name = arg->getName().getValue();
if (argsSet.find(name) != argsSet.end()) {
return reportError({
"Two arguments with same name to function",
node.getName().getValue(), ":", name
});
}
argsSet.insert(name);
} }
llvm::FunctionType *ftype = llvm::FunctionType::get( llvm::FunctionType *ftype = llvm::FunctionType::get(
LLVMType(node.getType()), argtypes, false LLVMType(node.getType()), argTypes, false
); );
llvm::Function *func = llvm::Function::Create( llvm::Function *func = llvm::Function::Create(
@ -253,11 +307,17 @@ void BitcodeEmitter::emit(Function const& node) {
func = module->getFunction(node.getName().getValue()); func = module->getFunction(node.getName().getValue());
if (!func->empty()) { if (!func->empty()) {
// TODO redefinition return reportError({
"Redefining function", node.getName().getValue()
});
} }
if (func->arg_size() != node.getArgs().size()) { if (func->arg_size() != node.getArgs().size()) {
// TODO different args return reportError({
"Argument number mismatch in definition vs declaration,",
"expected", std::to_string(func->arg_size()),
"given", std::to_string(node.getArgs().size())
});
} }
} }
@ -267,8 +327,6 @@ void BitcodeEmitter::emit(Function const& node) {
++argToEmit; ++argToEmit;
} }
// TODO check repeated arg names
llvm::BasicBlock *bb = llvm::BasicBlock::Create( llvm::BasicBlock *bb = llvm::BasicBlock::Create(
getGlobalContext(), "entry", func getGlobalContext(), "entry", func
); );
@ -284,48 +342,60 @@ void BitcodeEmitter::emit(Function const& node) {
} }
for (Statement const* stat: node.getBody()) { for (Statement const* stat: node.getBody()) {
stat->emit(this); GUARDED(stat->emit(this));
} }
verifyFunction(*func); verifyFunction(*func);
d->scope.leave(); d->scope.leave();
return true;
} }
void BitcodeEmitter::emit(Module const& node) {} bool BitcodeEmitter::emit(Module const& node) {
return true;
}
void BitcodeEmitter::emit(Program const& program) { bool BitcodeEmitter::emit(Program const& program) {
for (Function const* function: program.getFunctions()) { for (Function const* function: program.getFunctions()) {
function->emit(this); GUARDED(function->emit(this));
} }
if (program.getMain()) { if (program.getMain()) {
program.getMain()->emit(this); GUARDED(program.getMain()->emit(this));
} }
// TODO modules // TODO modules
} }
void BitcodeEmitter::emit(Id const& node) { bool BitcodeEmitter::emit(Id const& node) {
auto value = d->scope.lookup(node.getValue()); auto value = d->scope.lookup(node.getValue());
if (!value) { if (!value) {
// TODO variable not defined return reportError({
"Undefined variable", node.getValue()
});
} }
d->retval = d->builder.CreateLoad(*value, node.getValue().c_str()); d->retval = d->builder.CreateLoad(*value, node.getValue().c_str());
return true;
} }
void BitcodeEmitter::emit(Integer const& node) { bool BitcodeEmitter::emit(Integer const& node) {
d->retval = llvm::ConstantInt::get( d->retval = llvm::ConstantInt::get(
getGlobalContext(), llvm::APInt(64, node.getValue(), true) getGlobalContext(), llvm::APInt(64, node.getValue(), true)
); );
return true;
} }
void BitcodeEmitter::emit(Float const& node) { bool BitcodeEmitter::emit(Float const& node) {
d->retval = llvm::ConstantFP::get( d->retval = llvm::ConstantFP::get(
getGlobalContext(), llvm::APFloat(node.getValue()) getGlobalContext(), llvm::APFloat(node.getValue())
); );
return true;
} }
static inline static inline
@ -394,23 +464,27 @@ void createOp(BitcodeEmitter::Private *d, llvm::Value *left, Operator op, llvm::
#undef HANDLE #undef HANDLE
#undef HANDLE_INT_ONLY #undef HANDLE_INT_ONLY
void BitcodeEmitter::emit(BinaryExpression const& expression) { bool BitcodeEmitter::emit(BinaryExpression const& expression) {
expression.getLeft().emit(this); GUARDED(expression.getLeft().emit(this));
llvm::Value *left = d->retval; llvm::Value *left = d->retval;
expression.getRight().emit(this); GUARDED(expression.getRight().emit(this));
llvm::Value *right = d->retval; llvm::Value *right = d->retval;
createOp(d, left, expression.getOperator(), right); createOp(d, left, expression.getOperator(), right);
return true;
} }
void BitcodeEmitter::emitSemiExpression(Id const& left, SemiExpression const& right) { bool BitcodeEmitter::emitSemiExpression(Id const& left, SemiExpression const& right) {
left.emit(this); GUARDED(left.emit(this));
llvm::Value *lhs = d->retval; llvm::Value *lhs = d->retval;
right.getLeft().emit(this); GUARDED(right.getLeft().emit(this));
llvm::Value *rhs = d->retval; llvm::Value *rhs = d->retval;
createOp(d, lhs, right.getOperator(), rhs); createOp(d, lhs, right.getOperator(), rhs);
return true;
} }

View File

@ -38,24 +38,24 @@ public:
BitcodeEmitter(BitcodeEmitter &) = delete; BitcodeEmitter(BitcodeEmitter &) = delete;
virtual ~BitcodeEmitter(); virtual ~BitcodeEmitter();
virtual void emit(Return const&) override; virtual bool emit(Return const&) override;
virtual void emit(Loop const&) override; virtual bool emit(Loop const&) override;
virtual void emit(VarDeclaration const&) override; virtual bool emit(VarDeclaration const&) override;
virtual void emit(Assignment const&) override; virtual bool emit(Assignment const&) override;
virtual void emit(Print const&) override; virtual bool emit(Print const&) override;
virtual void emit(Input const&) override; virtual bool emit(Input const&) override;
virtual void emit(Abort const&) override; virtual bool emit(Abort const&) override;
virtual void emit(Assert const&) override; virtual bool emit(Assert const&) override;
virtual void emit(Branch const&) override; virtual bool emit(Branch const&) override;
virtual void emit(Function const&) override; virtual bool emit(Function const&) override;
virtual void emit(Module const&) override; virtual bool emit(Module const&) override;
virtual void emit(Program const&) override; virtual bool emit(Program const&) override;
virtual void emit(Id const&) override; virtual bool emit(Id const&) override;
virtual void emit(Integer const&) override; virtual bool emit(Integer const&) override;
virtual void emit(Float const&) override; virtual bool emit(Float const&) override;
virtual void emit(FunctionCall const&) override; virtual bool emit(FunctionCall const&) override;
virtual void emit(BinaryExpression const&) override; virtual bool emit(BinaryExpression const&) override;
llvm::Module const& getModule() const { llvm::Module const& getModule() const {
return *module; return *module;
@ -64,7 +64,7 @@ public:
struct Private; struct Private;
private: private:
void emitSemiExpression(Id const& left, SemiExpression const& right); bool emitSemiExpression(Id const& left, SemiExpression const& right);
std::unique_ptr<llvm::Module> module; std::unique_ptr<llvm::Module> module;
Private *d; Private *d;

View File

@ -25,6 +25,8 @@
using namespace monicelli; using namespace monicelli;
// Yes, that's right, no ending ;
#define GUARDED(call) if (!(call)) return false
static const std::string STATEMENT_TERMINATOR = ";\n"; static const std::string STATEMENT_TERMINATOR = ";\n";
static const std::string BLOCK = " "; static const std::string BLOCK = " ";
@ -38,15 +40,17 @@ void CppEmitter::dedent() {
indent_chars -= 1; indent_chars -= 1;
} }
void CppEmitter::emitIndent() { bool CppEmitter::emitIndent() {
for (int i = 0; i < indent_chars; ++i) { for (int i = 0; i < indent_chars; ++i) {
stream << BLOCK; stream << BLOCK;
} }
return stream;
} }
void CppEmitter::emit(Program const& program) { bool CppEmitter::emit(Program const& program) {
for (Module m: program.getModules()) { for (Module m: program.getModules()) {
m.emit(this); GUARDED(m.emit(this));
stream << "\n"; stream << "\n";
} }
@ -64,52 +68,61 @@ void CppEmitter::emit(Program const& program) {
} }
for (Function *function: program.getFunctions()) { for (Function *function: program.getFunctions()) {
function->emit(this); GUARDED(function->emit(this));
} }
if (program.getMain()) { if (program.getMain()) {
program.getMain()->emit(this); GUARDED(program.getMain()->emit(this));
}
} }
void CppEmitter::emitStatements(PointerList<Statement> const& node) { return stream;
}
bool CppEmitter::emitStatements(PointerList<Statement> const& node) {
for (Statement *s: node) { for (Statement *s: node) {
emitIndent(); emitIndent();
s->emit(this); GUARDED(s->emit(this));
stream << STATEMENT_TERMINATOR; stream << STATEMENT_TERMINATOR;
} }
return stream;
} }
void CppEmitter::emitMain(Function const& main) { bool CppEmitter::emitMain(Function const& main) {
stream << "int main() {\n"; stream << "int main() {\n";
indent(); indent();
emitStatements(main.getBody()); emitStatements(main.getBody());
dedent(); dedent();
stream << "}\n"; stream << "}\n";
return stream;
} }
void CppEmitter::emit(Id const& id) { bool CppEmitter::emit(Id const& id) {
stream << id.getValue(); stream << id.getValue();
return stream;
} }
void CppEmitter::emit(Integer const& num) { bool CppEmitter::emit(Integer const& num) {
stream << num.getValue(); stream << num.getValue();
return stream;
} }
void CppEmitter::emit(Float const& num) { bool CppEmitter::emit(Float const& num) {
stream << num.getValue(); stream << num.getValue();
return stream;
} }
void CppEmitter::emit(Return const& node) { bool CppEmitter::emit(Return const& node) {
stream << "return"; stream << "return";
if (node.getExpression()) { if (node.getExpression()) {
stream << ' '; stream << ' ';
node.getExpression()->emit(this); GUARDED(node.getExpression()->emit(this));
}
} }
void CppEmitter::emit(Print const& node) { return stream;
}
bool CppEmitter::emit(Print const& node) {
bool needsBraces = bool needsBraces =
(dynamic_cast<SimpleExpression const*>(&node.getExpression()) == nullptr) (dynamic_cast<SimpleExpression const*>(&node.getExpression()) == nullptr)
&& &&
@ -121,45 +134,55 @@ void CppEmitter::emit(Print const& node) {
stream << '('; stream << '(';
} }
node.getExpression().emit(this); GUARDED(node.getExpression().emit(this));
if (needsBraces) { if (needsBraces) {
stream << ')'; stream << ')';
} }
stream << " << std::endl"; stream << " << std::endl";
return stream;
} }
void CppEmitter::emit(Input const& node) { bool CppEmitter::emit(Input const& node) {
stream << "std::cout << \""; stream << "std::cout << \"";
node.getVariable().emit(this); GUARDED(node.getVariable().emit(this));
stream << "? \";\n"; stream << "? \";\n";
emitIndent(); emitIndent();
stream << "std::cin >> "; stream << "std::cin >> ";
node.getVariable().emit(this); GUARDED(node.getVariable().emit(this));
return stream;
} }
void CppEmitter::emit(Abort const&) { bool CppEmitter::emit(Abort const&) {
stream << "std::exit(1)"; stream << "std::exit(1)";
return stream;
} }
void CppEmitter::emit(Assert const& node) { bool CppEmitter::emit(Assert const& node) {
stream << "assert("; stream << "assert(";
node.getExpression().emit(this); GUARDED(node.getExpression().emit(this));
stream << ")"; stream << ")";
return stream;
} }
void CppEmitter::emit(Loop const& loop) { bool CppEmitter::emit(Loop const& loop) {
stream << "do {\n"; stream << "do {\n";
indent(); indent();
emitStatements(loop.getBody()); emitStatements(loop.getBody());
dedent(); dedent();
emitIndent(); emitIndent();
stream << "} while ("; stream << "} while (";
loop.getCondition().emit(this); GUARDED(loop.getCondition().emit(this));
stream << ")"; stream << ")";
return stream;
} }
void CppEmitter::emitBranchCase(BranchCase const& node) { bool CppEmitter::emitBranchCase(BranchCase const& node) {
emitBranchCondition(node.getCondition()); emitBranchCondition(node.getCondition());
stream << ") {\n"; stream << ") {\n";
indent(); indent();
@ -167,14 +190,16 @@ void CppEmitter::emitBranchCase(BranchCase const& node) {
dedent(); dedent();
emitIndent(); emitIndent();
stream << "}"; stream << "}";
return stream;
} }
void CppEmitter::emit(Branch const& branch) { bool CppEmitter::emit(Branch const& branch) {
auto &body = branch.getBody(); auto &body = branch.getBody();
auto &var = branch.getVar(); auto &var = branch.getVar();
stream << "if ("; stream << "if (";
var.emit(this); GUARDED(var.emit(this));
if (body.getCases().size() > 0) { if (body.getCases().size() > 0) {
BranchCase *last = body.getCases().back(); BranchCase *last = body.getCases().back();
@ -182,13 +207,13 @@ void CppEmitter::emit(Branch const& branch) {
emitBranchCase(*cas); emitBranchCase(*cas);
if (cas != last) { if (cas != last) {
stream << " else if ("; stream << " else if (";
var.emit(this); GUARDED(var.emit(this));
} }
} }
} }
if (!body.getElse()) { if (!body.getElse()) {
return; return stream;
} }
stream << " else {\n"; stream << " else {\n";
@ -197,40 +222,50 @@ void CppEmitter::emit(Branch const& branch) {
dedent(); dedent();
emitIndent(); emitIndent();
stream << "}"; stream << "}";
return stream;
} }
void CppEmitter::emit(Assignment const& assignment) { bool CppEmitter::emit(Assignment const& assignment) {
assignment.getName().emit(this); GUARDED(assignment.getName().emit(this));
stream << " = "; stream << " = ";
assignment.getValue().emit(this); GUARDED(assignment.getValue().emit(this));
return stream;
} }
void CppEmitter::emitFunctionArglist(PointerList<Expression> const& args) { bool CppEmitter::emitFunctionArglist(PointerList<Expression> const& args) {
Expression *last = args.back(); Expression *last = args.back();
for (Expression const* arg: args) { for (Expression const* arg: args) {
arg->emit(this); GUARDED(arg->emit(this));
if (arg != last) { if (arg != last) {
stream << ", "; stream << ", ";
} }
} }
return stream;
} }
void CppEmitter::emit(FunctionCall const& funcall) { bool CppEmitter::emit(FunctionCall const& funcall) {
funcall.getName().emit(this); GUARDED(funcall.getName().emit(this));
stream << "("; stream << "(";
emitFunctionArglist(funcall.getArgs()); emitFunctionArglist(funcall.getArgs());
stream << ")"; stream << ")";
return stream;
} }
void CppEmitter::emit(Function const& function) { bool CppEmitter::emit(Function const& function) {
emitFunctionSignature(function); emitFunctionSignature(function);
stream << " {\n"; stream << " {\n";
indent(); indent();
emitStatements(function.getBody()); emitStatements(function.getBody());
dedent(); dedent();
stream << "}\n\n"; stream << "}\n\n";
return stream;
} }
std::ostream& operator<<(std::ostream &stream, Type const& type) { std::ostream& operator<<(std::ostream &stream, Type const& type) {
@ -258,40 +293,48 @@ std::ostream& operator<<(std::ostream &stream, Type const& type) {
return stream; return stream;
} }
void CppEmitter::emitFunctionParams(PointerList<FunArg> const& funargs) { bool CppEmitter::emitFunctionParams(PointerList<FunArg> const& funargs) {
FunArg *last = funargs.back(); FunArg *last = funargs.back();
for (FunArg const* funarg: funargs) { for (FunArg const* funarg: funargs) {
stream << funarg->getType() << (funarg->isPointer()? "* ": " "); stream << funarg->getType() << (funarg->isPointer()? "* ": " ");
funarg->getName().emit(this); GUARDED(funarg->getName().emit(this));
if (funarg != last) { if (funarg != last) {
stream << ", "; stream << ", ";
} }
} }
return stream;
} }
void CppEmitter::emit(Module const& module) { bool CppEmitter::emit(Module const& module) {
bool system = (module.getType() == Module::SYSTEM); bool system = (module.getType() == Module::SYSTEM);
stream << "#include " << (system? '<': '"') << module.getName() << (system? '>': '"'); stream << "#include " << (system? '<': '"') << module.getName() << (system? '>': '"');
return stream;
} }
void CppEmitter::emitFunctionSignature(Function const& function) { bool CppEmitter::emitFunctionSignature(Function const& function) {
stream << function.getType() << ' '; stream << function.getType() << ' ';
function.getName().emit(this); GUARDED(function.getName().emit(this));
stream << "("; stream << "(";
emitFunctionParams(function.getArgs()); emitFunctionParams(function.getArgs());
stream << ")"; stream << ")";
return stream;
} }
void CppEmitter::emit(VarDeclaration const& decl) { bool CppEmitter::emit(VarDeclaration const& decl) {
stream << decl.getType() << ' '; stream << decl.getType() << ' ';
if (decl.isPointer()) stream << '*'; if (decl.isPointer()) stream << '*';
decl.getId().emit(this); GUARDED(decl.getId().emit(this));
if (decl.getInitializer()) { if (decl.getInitializer()) {
stream << " = "; stream << " = ";
decl.getInitializer()->emit(this); GUARDED(decl.getInitializer()->emit(this));
} }
return stream;
} }
std::ostream& operator<<(std::ostream &stream, Operator op) { std::ostream& operator<<(std::ostream &stream, Operator op) {
@ -334,18 +377,22 @@ std::ostream& operator<<(std::ostream &stream, Operator op) {
return stream; return stream;
} }
void CppEmitter::emit(BinaryExpression const& node) { bool CppEmitter::emit(BinaryExpression const& node) {
node.getLeft().emit(this); GUARDED(node.getLeft().emit(this));
stream << ' ' << node.getOperator() << ' '; stream << ' ' << node.getOperator() << ' ';
node.getRight().emit(this); GUARDED(node.getRight().emit(this));
return stream;
} }
void CppEmitter::emitBranchCondition(SemiExpression const& node) { bool CppEmitter::emitBranchCondition(SemiExpression const& node) {
bool braces = (dynamic_cast<SimpleExpression const*>(&node.getLeft()) == nullptr); bool braces = (dynamic_cast<SimpleExpression const*>(&node.getLeft()) == nullptr);
stream << ' ' << node.getOperator() << ' '; stream << ' ' << node.getOperator() << ' ';
if (braces) stream << "("; if (braces) stream << "(";
node.getLeft().emit(this); GUARDED(node.getLeft().emit(this));
if (braces) stream << ")"; if (braces) stream << ")";
return stream;
} }

View File

@ -31,34 +31,34 @@ class CppEmitter: public Emitter {
public: public:
CppEmitter(std::ostream *stream): stream(*stream), indent_chars(0) {} CppEmitter(std::ostream *stream): stream(*stream), indent_chars(0) {}
virtual void emit(Return const&) override; virtual bool emit(Return const&) override;
virtual void emit(Loop const&) override; virtual bool emit(Loop const&) override;
virtual void emit(VarDeclaration const&) override; virtual bool emit(VarDeclaration const&) override;
virtual void emit(Assignment const&) override; virtual bool emit(Assignment const&) override;
virtual void emit(Print const&) override; virtual bool emit(Print const&) override;
virtual void emit(Input const&) override; virtual bool emit(Input const&) override;
virtual void emit(Abort const&) override; virtual bool emit(Abort const&) override;
virtual void emit(Assert const&) override; virtual bool emit(Assert const&) override;
virtual void emit(Branch const&) override; virtual bool emit(Branch const&) override;
virtual void emit(Function const&) override; virtual bool emit(Function const&) override;
virtual void emit(Module const&) override; virtual bool emit(Module const&) override;
virtual void emit(Program const&) override; virtual bool emit(Program const&) override;
virtual void emit(FunctionCall const&) override; virtual bool emit(FunctionCall const&) override;
virtual void emit(Id const&) override; virtual bool emit(Id const&) override;
virtual void emit(Integer const&) override; virtual bool emit(Integer const&) override;
virtual void emit(Float const&) override; virtual bool emit(Float const&) override;
virtual void emit(BinaryExpression const&) override; virtual bool emit(BinaryExpression const&) override;
private: private:
void emitIndent(); bool emitIndent();
void emitFunctionSignature(Function const& function); bool emitFunctionSignature(Function const& function);
void emitFunctionParams(PointerList<FunArg> const& funargs); bool emitFunctionParams(PointerList<FunArg> const& funargs);
void emitFunctionArglist(PointerList<Expression> const& args); bool emitFunctionArglist(PointerList<Expression> const& args);
void emitStatements(PointerList<Statement> const& node); bool emitStatements(PointerList<Statement> const& node);
void emitBranchCondition(SemiExpression const& node); bool emitBranchCondition(SemiExpression const& node);
void emitBranchCase(BranchCase const& node); bool emitBranchCase(BranchCase const& node);
void emitMain(Function const& main); bool emitMain(Function const& main);
void indent(); void indent();
void dedent(); void dedent();

View File

@ -45,24 +45,24 @@ class BinaryExpression;
class Emitter { class Emitter {
public: public:
virtual void emit(Return const&) = 0; virtual bool emit(Return const&) = 0;
virtual void emit(Loop const&) = 0; virtual bool emit(Loop const&) = 0;
virtual void emit(VarDeclaration const&) = 0; virtual bool emit(VarDeclaration const&) = 0;
virtual void emit(Assignment const&) = 0; virtual bool emit(Assignment const&) = 0;
virtual void emit(Print const&) = 0; virtual bool emit(Print const&) = 0;
virtual void emit(Input const&) = 0; virtual bool emit(Input const&) = 0;
virtual void emit(Abort const&) = 0; virtual bool emit(Abort const&) = 0;
virtual void emit(Assert const&) = 0; virtual bool emit(Assert const&) = 0;
virtual void emit(Branch const&) = 0; virtual bool emit(Branch const&) = 0;
virtual void emit(Function const&) = 0; virtual bool emit(Function const&) = 0;
virtual void emit(Module const&) = 0; virtual bool emit(Module const&) = 0;
virtual void emit(Program const&) = 0; virtual bool emit(Program const&) = 0;
virtual void emit(Id const&) = 0; virtual bool emit(Id const&) = 0;
virtual void emit(Integer const&) = 0; virtual bool emit(Integer const&) = 0;
virtual void emit(Float const&) = 0; virtual bool emit(Float const&) = 0;
virtual void emit(FunctionCall const&) = 0; virtual bool emit(FunctionCall const&) = 0;
virtual void emit(BinaryExpression const&) = 0; virtual bool emit(BinaryExpression const&) = 0;
}; };
} }

View File

@ -50,22 +50,15 @@ enum class Operator {
class Emittable { class Emittable {
public: public:
virtual ~Emittable() {} virtual ~Emittable() {}
virtual void emit(Emitter *emitter) const = 0; virtual bool emit(Emitter *emitter) const = 0;
}; };
class Statement: public Emittable { class Statement: public Emittable {};
public:
virtual void emit(Emitter *) const {}
};
class Expression: public Emittable { class Expression: public Emittable {};
public:
virtual void emit(Emitter *) const {}
};
class SimpleExpression: public Expression { class SimpleExpression: public Expression {};
};
class SemiExpression { class SemiExpression {
public: public:
@ -89,8 +82,8 @@ class Id: public SimpleExpression {
public: public:
explicit Id(std::string *c): value(c) {} explicit Id(std::string *c): value(c) {}
virtual void emit(Emitter *emitter) const { virtual bool emit(Emitter *emitter) const {
emitter->emit(*this); return emitter->emit(*this);
} }
std::string const& getValue() const { std::string const& getValue() const {
@ -109,8 +102,8 @@ class Integer: public Number {
public: public:
Integer(long i): value(i) {} Integer(long i): value(i) {}
virtual void emit(Emitter *emitter) const { virtual bool emit(Emitter *emitter) const {
emitter->emit(*this); return emitter->emit(*this);
} }
long getValue() const { long getValue() const {
@ -126,8 +119,8 @@ class Float: public Number {
public: public:
Float(double f): value(f) {} Float(double f): value(f) {}
virtual void emit(Emitter *emitter) const { virtual bool emit(Emitter *emitter) const {
emitter->emit(*this); return emitter->emit(*this);
} }
double getValue() const { double getValue() const {
@ -143,8 +136,8 @@ class Return: public Statement {
public: public:
explicit Return(Expression *e): expression(e) {} explicit Return(Expression *e): expression(e) {}
virtual void emit(Emitter *emitter) const { virtual bool emit(Emitter *emitter) const {
emitter->emit(*this); return emitter->emit(*this);
} }
boost::optional<Expression const&> getExpression() const { boost::optional<Expression const&> getExpression() const {
@ -160,8 +153,8 @@ class Loop: public Statement {
public: public:
Loop(PointerList<Statement> *b, Expression *c): body(b), condition(c) {} Loop(PointerList<Statement> *b, Expression *c): body(b), condition(c) {}
virtual void emit(Emitter *emitter) const { virtual bool emit(Emitter *emitter) const {
emitter->emit(*this); return emitter->emit(*this);
} }
PointerList<Statement> const& getBody() const { PointerList<Statement> const& getBody() const {
@ -183,8 +176,8 @@ public:
VarDeclaration(Id *n, Type t, bool p, Expression *i): VarDeclaration(Id *n, Type t, bool p, Expression *i):
name(n), point(p), init(i), type(t) {} name(n), point(p), init(i), type(t) {}
virtual void emit(Emitter *emitter) const { virtual bool emit(Emitter *emitter) const {
emitter->emit(*this); return emitter->emit(*this);
} }
Id const& getId() const { Id const& getId() const {
@ -215,8 +208,8 @@ class Assignment: public Statement {
public: public:
Assignment(Id *n, Expression *v): name(n), value(v) {} Assignment(Id *n, Expression *v): name(n), value(v) {}
virtual void emit(Emitter *emitter) const { virtual bool emit(Emitter *emitter) const {
emitter->emit(*this); return emitter->emit(*this);
} }
Id const& getName() const { Id const& getName() const {
@ -237,8 +230,8 @@ class Print: public Statement {
public: public:
explicit Print(Expression *e): expression(e) {} explicit Print(Expression *e): expression(e) {}
virtual void emit(Emitter *emitter) const { virtual bool emit(Emitter *emitter) const {
emitter->emit(*this); return emitter->emit(*this);
} }
Expression const& getExpression() const { Expression const& getExpression() const {
@ -254,8 +247,8 @@ class Input: public Statement {
public: public:
explicit Input(Id *v): variable(v) {} explicit Input(Id *v): variable(v) {}
virtual void emit(Emitter *emitter) const { virtual bool emit(Emitter *emitter) const {
emitter->emit(*this); return emitter->emit(*this);
} }
Id const& getVariable() const { Id const& getVariable() const {
@ -269,8 +262,8 @@ private:
class Abort: public Statement { class Abort: public Statement {
public: public:
virtual void emit(Emitter *emitter) const { virtual bool emit(Emitter *emitter) const {
emitter->emit(*this); return emitter->emit(*this);
} }
}; };
@ -279,8 +272,8 @@ class Assert: public Statement {
public: public:
explicit Assert(Expression *e): expression(e) {} explicit Assert(Expression *e): expression(e) {}
virtual void emit(Emitter *emitter) const { virtual bool emit(Emitter *emitter) const {
emitter->emit(*this); return emitter->emit(*this);
} }
Expression const& getExpression() const { Expression const& getExpression() const {
@ -296,8 +289,8 @@ class FunctionCall: public Statement, public Expression {
public: public:
FunctionCall(Id *n, PointerList<Expression> *a): name(n), args(a) {} FunctionCall(Id *n, PointerList<Expression> *a): name(n), args(a) {}
virtual void emit(Emitter *emitter) const { virtual bool emit(Emitter *emitter) const {
emitter->emit(*this); return emitter->emit(*this);
} }
Id const& getName() const { Id const& getName() const {
@ -353,8 +346,8 @@ public:
Branch(Id *v, Branch::Body *b): var(v), body(b) {} Branch(Id *v, Branch::Body *b): var(v), body(b) {}
virtual void emit(Emitter *emitter) const { virtual bool emit(Emitter *emitter) const {
emitter->emit(*this); return emitter->emit(*this);
} }
Id const& getVar() const { Id const& getVar() const {
@ -401,8 +394,8 @@ public:
Function(Id *n, Type r, PointerList<FunArg> *a, PointerList<Statement> *b): Function(Id *n, Type r, PointerList<FunArg> *a, PointerList<Statement> *b):
name(n), type(r), args(a), body(b) {} name(n), type(r), args(a), body(b) {}
virtual void emit(Emitter *emitter) const { virtual bool emit(Emitter *emitter) const {
emitter->emit(*this); return emitter->emit(*this);
} }
Id const& getName() const { Id const& getName() const {
@ -437,8 +430,8 @@ public:
Module(const std::string &n, Type s): name(n), type(s) {} Module(const std::string &n, Type s): name(n), type(s) {}
virtual void emit(Emitter *emitter) const { virtual bool emit(Emitter *emitter) const {
emitter->emit(*this); return emitter->emit(*this);
} }
bool operator==(const Module &other) const noexcept { bool operator==(const Module &other) const noexcept {
@ -480,8 +473,8 @@ namespace monicelli {
class Program: public Emittable { class Program: public Emittable {
public: public:
virtual void emit(Emitter *emitter) const { virtual bool emit(Emitter *emitter) const {
emitter->emit(*this); return emitter->emit(*this);
} }
void setMain(Function *m) { void setMain(Function *m) {
@ -521,8 +514,8 @@ public:
BinaryExpression(Expression *l, Operator op, Expression *r): BinaryExpression(Expression *l, Operator op, Expression *r):
left(l), op(op), right(r) {} left(l), op(op), right(r) {}
virtual void emit(Emitter *emitter) const { virtual bool emit(Emitter *emitter) const {
emitter->emit(*this); return emitter->emit(*this);
} }
Expression const& getLeft() const { Expression const& getLeft() const {