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:
parent
2ce76a1dfd
commit
b7be4dc37f
|
@ -29,6 +29,14 @@
|
|||
|
||||
#include <string>
|
||||
#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;
|
||||
|
@ -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() {
|
||||
module = std::unique_ptr<llvm::Module>(new llvm::Module("monicelli", getGlobalContext()));
|
||||
d = new Private;
|
||||
|
@ -84,16 +102,18 @@ BitcodeEmitter::~BitcodeEmitter() {
|
|||
delete d;
|
||||
}
|
||||
|
||||
void BitcodeEmitter::emit(Return const& node) {
|
||||
bool BitcodeEmitter::emit(Return const& node) {
|
||||
if (node.getExpression()) {
|
||||
node.getExpression()->emit(this);
|
||||
GUARDED(node.getExpression()->emit(this));
|
||||
d->builder.CreateRet(d->retval);
|
||||
} else {
|
||||
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::BasicBlock *body = llvm::BasicBlock::Create(
|
||||
|
@ -105,11 +125,11 @@ void BitcodeEmitter::emit(Loop const& node) {
|
|||
|
||||
d->scope.enter();
|
||||
for (Statement const* statement: node.getBody()) {
|
||||
statement->emit(this);
|
||||
GUARDED(statement->emit(this));
|
||||
}
|
||||
d->scope.leave();
|
||||
|
||||
node.getCondition().emit(this);
|
||||
GUARDED(node.getCondition().emit(this));
|
||||
|
||||
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.SetInsertPoint(after);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BitcodeEmitter::emit(VarDeclaration const& node) {
|
||||
bool BitcodeEmitter::emit(VarDeclaration const& node) {
|
||||
llvm::Function *father = d->builder.GetInsertBlock()->getParent();
|
||||
llvm::AllocaInst *alloc = allocateVar(
|
||||
father, node.getId(), LLVMType(node.getType())
|
||||
);
|
||||
|
||||
if (node.getInitializer()) {
|
||||
node.getInitializer()->emit(this);
|
||||
GUARDED(node.getInitializer()->emit(this));
|
||||
d->builder.CreateStore(d->retval, alloc);
|
||||
}
|
||||
|
||||
// TODO pointers
|
||||
|
||||
d->scope.push(node.getId().getValue(), alloc);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BitcodeEmitter::emit(Assignment const& node) {
|
||||
node.getValue().emit(this);
|
||||
bool BitcodeEmitter::emit(Assignment const& node) {
|
||||
GUARDED(node.getValue().emit(this));
|
||||
auto var = d->scope.lookup(node.getName().getValue());
|
||||
|
||||
if (!var) {
|
||||
// TODO undefined var
|
||||
return reportError({
|
||||
"Attempting assignment to undefined var", node.getName().getValue()
|
||||
});
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
if (callee == 0) {
|
||||
// TODO Error
|
||||
return reportError({
|
||||
"Attempting to call undefined function", node.getName().getValue()
|
||||
});
|
||||
}
|
||||
|
||||
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;
|
||||
for (Expression const* arg: node.getArgs()) {
|
||||
arg->emit(this);
|
||||
GUARDED(arg->emit(this));
|
||||
callargs.push_back(d->retval);
|
||||
}
|
||||
|
||||
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();
|
||||
llvm::Function *func = d->builder.GetInsertBlock()->getParent();
|
||||
|
||||
|
@ -204,7 +244,7 @@ void BitcodeEmitter::emit(Branch const& node) {
|
|||
d->builder.SetInsertPoint(thenbb);
|
||||
d->scope.enter();
|
||||
for (Statement const* statement: cas->getBody()) {
|
||||
statement->emit(this);
|
||||
GUARDED(statement->emit(this));
|
||||
}
|
||||
d->scope.leave();
|
||||
d->builder.CreateBr(mergebb);
|
||||
|
@ -221,7 +261,7 @@ void BitcodeEmitter::emit(Branch const& node) {
|
|||
if (body.getElse()) {
|
||||
d->scope.enter();
|
||||
for (Statement const* statement: *body.getElse()) {
|
||||
statement->emit(this);
|
||||
GUARDED(statement->emit(this));
|
||||
}
|
||||
d->scope.leave();
|
||||
d->builder.CreateBr(mergebb);
|
||||
|
@ -229,19 +269,33 @@ void BitcodeEmitter::emit(Branch const& node) {
|
|||
|
||||
func->getBasicBlockList().push_back(mergebb);
|
||||
d->builder.SetInsertPoint(mergebb);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BitcodeEmitter::emit(Function const& node) {
|
||||
bool BitcodeEmitter::emit(Function const& node) {
|
||||
d->scope.enter();
|
||||
|
||||
std::vector<llvm::Type*> argtypes;
|
||||
std::vector<llvm::Type*> argTypes;
|
||||
|
||||
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(
|
||||
LLVMType(node.getType()), argtypes, false
|
||||
LLVMType(node.getType()), argTypes, false
|
||||
);
|
||||
|
||||
llvm::Function *func = llvm::Function::Create(
|
||||
|
@ -253,11 +307,17 @@ void BitcodeEmitter::emit(Function const& node) {
|
|||
func = module->getFunction(node.getName().getValue());
|
||||
|
||||
if (!func->empty()) {
|
||||
// TODO redefinition
|
||||
return reportError({
|
||||
"Redefining function", node.getName().getValue()
|
||||
});
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// TODO check repeated arg names
|
||||
|
||||
llvm::BasicBlock *bb = llvm::BasicBlock::Create(
|
||||
getGlobalContext(), "entry", func
|
||||
);
|
||||
|
@ -284,48 +342,60 @@ void BitcodeEmitter::emit(Function const& node) {
|
|||
}
|
||||
|
||||
for (Statement const* stat: node.getBody()) {
|
||||
stat->emit(this);
|
||||
GUARDED(stat->emit(this));
|
||||
}
|
||||
|
||||
verifyFunction(*func);
|
||||
|
||||
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()) {
|
||||
function->emit(this);
|
||||
GUARDED(function->emit(this));
|
||||
}
|
||||
|
||||
if (program.getMain()) {
|
||||
program.getMain()->emit(this);
|
||||
GUARDED(program.getMain()->emit(this));
|
||||
}
|
||||
|
||||
// TODO modules
|
||||
}
|
||||
|
||||
void BitcodeEmitter::emit(Id const& node) {
|
||||
bool BitcodeEmitter::emit(Id const& node) {
|
||||
auto value = d->scope.lookup(node.getValue());
|
||||
|
||||
if (!value) {
|
||||
// TODO variable not defined
|
||||
return reportError({
|
||||
"Undefined variable", node.getValue()
|
||||
});
|
||||
}
|
||||
|
||||
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(
|
||||
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(
|
||||
getGlobalContext(), llvm::APFloat(node.getValue())
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline
|
||||
|
@ -394,23 +464,27 @@ void createOp(BitcodeEmitter::Private *d, llvm::Value *left, Operator op, llvm::
|
|||
#undef HANDLE
|
||||
#undef HANDLE_INT_ONLY
|
||||
|
||||
void BitcodeEmitter::emit(BinaryExpression const& expression) {
|
||||
expression.getLeft().emit(this);
|
||||
bool BitcodeEmitter::emit(BinaryExpression const& expression) {
|
||||
GUARDED(expression.getLeft().emit(this));
|
||||
llvm::Value *left = d->retval;
|
||||
|
||||
expression.getRight().emit(this);
|
||||
GUARDED(expression.getRight().emit(this));
|
||||
llvm::Value *right = d->retval;
|
||||
|
||||
createOp(d, left, expression.getOperator(), right);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BitcodeEmitter::emitSemiExpression(Id const& left, SemiExpression const& right) {
|
||||
left.emit(this);
|
||||
bool BitcodeEmitter::emitSemiExpression(Id const& left, SemiExpression const& right) {
|
||||
GUARDED(left.emit(this));
|
||||
llvm::Value *lhs = d->retval;
|
||||
|
||||
right.getLeft().emit(this);
|
||||
GUARDED(right.getLeft().emit(this));
|
||||
llvm::Value *rhs = d->retval;
|
||||
|
||||
createOp(d, lhs, right.getOperator(), rhs);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,24 +38,24 @@ public:
|
|||
BitcodeEmitter(BitcodeEmitter &) = delete;
|
||||
virtual ~BitcodeEmitter();
|
||||
|
||||
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(Branch const&) override;
|
||||
virtual void emit(Function const&) override;
|
||||
virtual void emit(Module const&) override;
|
||||
virtual void emit(Program const&) override;
|
||||
virtual bool emit(Return const&) override;
|
||||
virtual bool emit(Loop const&) override;
|
||||
virtual bool emit(VarDeclaration const&) override;
|
||||
virtual bool emit(Assignment const&) override;
|
||||
virtual bool emit(Print const&) override;
|
||||
virtual bool emit(Input const&) override;
|
||||
virtual bool emit(Abort const&) override;
|
||||
virtual bool emit(Assert const&) override;
|
||||
virtual bool emit(Branch const&) override;
|
||||
virtual bool emit(Function const&) override;
|
||||
virtual bool emit(Module const&) override;
|
||||
virtual bool emit(Program const&) override;
|
||||
|
||||
virtual void emit(Id const&) override;
|
||||
virtual void emit(Integer const&) override;
|
||||
virtual void emit(Float const&) override;
|
||||
virtual void emit(FunctionCall const&) override;
|
||||
virtual void emit(BinaryExpression const&) override;
|
||||
virtual bool emit(Id const&) override;
|
||||
virtual bool emit(Integer const&) override;
|
||||
virtual bool emit(Float const&) override;
|
||||
virtual bool emit(FunctionCall const&) override;
|
||||
virtual bool emit(BinaryExpression const&) override;
|
||||
|
||||
llvm::Module const& getModule() const {
|
||||
return *module;
|
||||
|
@ -64,7 +64,7 @@ public:
|
|||
struct Private;
|
||||
|
||||
private:
|
||||
void emitSemiExpression(Id const& left, SemiExpression const& right);
|
||||
bool emitSemiExpression(Id const& left, SemiExpression const& right);
|
||||
|
||||
std::unique_ptr<llvm::Module> module;
|
||||
Private *d;
|
||||
|
|
149
CppEmitter.cpp
149
CppEmitter.cpp
|
@ -25,6 +25,8 @@
|
|||
|
||||
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 BLOCK = " ";
|
||||
|
@ -38,15 +40,17 @@ void CppEmitter::dedent() {
|
|||
indent_chars -= 1;
|
||||
}
|
||||
|
||||
void CppEmitter::emitIndent() {
|
||||
bool CppEmitter::emitIndent() {
|
||||
for (int i = 0; i < indent_chars; ++i) {
|
||||
stream << BLOCK;
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
void CppEmitter::emit(Program const& program) {
|
||||
bool CppEmitter::emit(Program const& program) {
|
||||
for (Module m: program.getModules()) {
|
||||
m.emit(this);
|
||||
GUARDED(m.emit(this));
|
||||
stream << "\n";
|
||||
}
|
||||
|
||||
|
@ -64,52 +68,61 @@ void CppEmitter::emit(Program const& program) {
|
|||
}
|
||||
|
||||
for (Function *function: program.getFunctions()) {
|
||||
function->emit(this);
|
||||
GUARDED(function->emit(this));
|
||||
}
|
||||
|
||||
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) {
|
||||
emitIndent();
|
||||
s->emit(this);
|
||||
GUARDED(s->emit(this));
|
||||
stream << STATEMENT_TERMINATOR;
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
void CppEmitter::emitMain(Function const& main) {
|
||||
bool CppEmitter::emitMain(Function const& main) {
|
||||
stream << "int main() {\n";
|
||||
indent();
|
||||
emitStatements(main.getBody());
|
||||
dedent();
|
||||
stream << "}\n";
|
||||
return stream;
|
||||
}
|
||||
|
||||
void CppEmitter::emit(Id const& id) {
|
||||
bool CppEmitter::emit(Id const& id) {
|
||||
stream << id.getValue();
|
||||
return stream;
|
||||
}
|
||||
|
||||
void CppEmitter::emit(Integer const& num) {
|
||||
bool CppEmitter::emit(Integer const& num) {
|
||||
stream << num.getValue();
|
||||
return stream;
|
||||
}
|
||||
|
||||
void CppEmitter::emit(Float const& num) {
|
||||
bool CppEmitter::emit(Float const& num) {
|
||||
stream << num.getValue();
|
||||
return stream;
|
||||
}
|
||||
|
||||
void CppEmitter::emit(Return const& node) {
|
||||
bool CppEmitter::emit(Return const& node) {
|
||||
stream << "return";
|
||||
|
||||
if (node.getExpression()) {
|
||||
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 =
|
||||
(dynamic_cast<SimpleExpression const*>(&node.getExpression()) == nullptr)
|
||||
&&
|
||||
|
@ -121,45 +134,55 @@ void CppEmitter::emit(Print const& node) {
|
|||
stream << '(';
|
||||
}
|
||||
|
||||
node.getExpression().emit(this);
|
||||
GUARDED(node.getExpression().emit(this));
|
||||
|
||||
if (needsBraces) {
|
||||
stream << ')';
|
||||
}
|
||||
stream << " << std::endl";
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
void CppEmitter::emit(Input const& node) {
|
||||
bool CppEmitter::emit(Input const& node) {
|
||||
stream << "std::cout << \"";
|
||||
node.getVariable().emit(this);
|
||||
GUARDED(node.getVariable().emit(this));
|
||||
stream << "? \";\n";
|
||||
emitIndent();
|
||||
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)";
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
void CppEmitter::emit(Assert const& node) {
|
||||
bool CppEmitter::emit(Assert const& node) {
|
||||
stream << "assert(";
|
||||
node.getExpression().emit(this);
|
||||
GUARDED(node.getExpression().emit(this));
|
||||
stream << ")";
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
void CppEmitter::emit(Loop const& loop) {
|
||||
bool CppEmitter::emit(Loop const& loop) {
|
||||
stream << "do {\n";
|
||||
indent();
|
||||
emitStatements(loop.getBody());
|
||||
dedent();
|
||||
emitIndent();
|
||||
stream << "} while (";
|
||||
loop.getCondition().emit(this);
|
||||
GUARDED(loop.getCondition().emit(this));
|
||||
stream << ")";
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
void CppEmitter::emitBranchCase(BranchCase const& node) {
|
||||
bool CppEmitter::emitBranchCase(BranchCase const& node) {
|
||||
emitBranchCondition(node.getCondition());
|
||||
stream << ") {\n";
|
||||
indent();
|
||||
|
@ -167,14 +190,16 @@ void CppEmitter::emitBranchCase(BranchCase const& node) {
|
|||
dedent();
|
||||
emitIndent();
|
||||
stream << "}";
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
void CppEmitter::emit(Branch const& branch) {
|
||||
bool CppEmitter::emit(Branch const& branch) {
|
||||
auto &body = branch.getBody();
|
||||
auto &var = branch.getVar();
|
||||
|
||||
stream << "if (";
|
||||
var.emit(this);
|
||||
GUARDED(var.emit(this));
|
||||
|
||||
if (body.getCases().size() > 0) {
|
||||
BranchCase *last = body.getCases().back();
|
||||
|
@ -182,13 +207,13 @@ void CppEmitter::emit(Branch const& branch) {
|
|||
emitBranchCase(*cas);
|
||||
if (cas != last) {
|
||||
stream << " else if (";
|
||||
var.emit(this);
|
||||
GUARDED(var.emit(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!body.getElse()) {
|
||||
return;
|
||||
return stream;
|
||||
}
|
||||
|
||||
stream << " else {\n";
|
||||
|
@ -197,40 +222,50 @@ void CppEmitter::emit(Branch const& branch) {
|
|||
dedent();
|
||||
emitIndent();
|
||||
stream << "}";
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
void CppEmitter::emit(Assignment const& assignment) {
|
||||
assignment.getName().emit(this);
|
||||
bool CppEmitter::emit(Assignment const& assignment) {
|
||||
GUARDED(assignment.getName().emit(this));
|
||||
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();
|
||||
for (Expression const* arg: args) {
|
||||
arg->emit(this);
|
||||
GUARDED(arg->emit(this));
|
||||
if (arg != last) {
|
||||
stream << ", ";
|
||||
}
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
void CppEmitter::emit(FunctionCall const& funcall) {
|
||||
funcall.getName().emit(this);
|
||||
bool CppEmitter::emit(FunctionCall const& funcall) {
|
||||
GUARDED(funcall.getName().emit(this));
|
||||
stream << "(";
|
||||
emitFunctionArglist(funcall.getArgs());
|
||||
stream << ")";
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
void CppEmitter::emit(Function const& function) {
|
||||
bool CppEmitter::emit(Function const& function) {
|
||||
emitFunctionSignature(function);
|
||||
stream << " {\n";
|
||||
indent();
|
||||
emitStatements(function.getBody());
|
||||
dedent();
|
||||
stream << "}\n\n";
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream &stream, Type const& type) {
|
||||
|
@ -258,40 +293,48 @@ std::ostream& operator<<(std::ostream &stream, Type const& type) {
|
|||
return stream;
|
||||
}
|
||||
|
||||
void CppEmitter::emitFunctionParams(PointerList<FunArg> const& funargs) {
|
||||
bool CppEmitter::emitFunctionParams(PointerList<FunArg> const& funargs) {
|
||||
FunArg *last = funargs.back();
|
||||
|
||||
for (FunArg const* funarg: funargs) {
|
||||
stream << funarg->getType() << (funarg->isPointer()? "* ": " ");
|
||||
funarg->getName().emit(this);
|
||||
GUARDED(funarg->getName().emit(this));
|
||||
if (funarg != last) {
|
||||
stream << ", ";
|
||||
}
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
void CppEmitter::emit(Module const& module) {
|
||||
bool CppEmitter::emit(Module const& module) {
|
||||
bool system = (module.getType() == Module::SYSTEM);
|
||||
stream << "#include " << (system? '<': '"') << module.getName() << (system? '>': '"');
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
void CppEmitter::emitFunctionSignature(Function const& function) {
|
||||
bool CppEmitter::emitFunctionSignature(Function const& function) {
|
||||
stream << function.getType() << ' ';
|
||||
function.getName().emit(this);
|
||||
GUARDED(function.getName().emit(this));
|
||||
stream << "(";
|
||||
emitFunctionParams(function.getArgs());
|
||||
stream << ")";
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
void CppEmitter::emit(VarDeclaration const& decl) {
|
||||
bool CppEmitter::emit(VarDeclaration const& decl) {
|
||||
stream << decl.getType() << ' ';
|
||||
if (decl.isPointer()) stream << '*';
|
||||
decl.getId().emit(this);
|
||||
GUARDED(decl.getId().emit(this));
|
||||
|
||||
if (decl.getInitializer()) {
|
||||
stream << " = ";
|
||||
decl.getInitializer()->emit(this);
|
||||
GUARDED(decl.getInitializer()->emit(this));
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream &stream, Operator op) {
|
||||
|
@ -334,18 +377,22 @@ std::ostream& operator<<(std::ostream &stream, Operator op) {
|
|||
return stream;
|
||||
}
|
||||
|
||||
void CppEmitter::emit(BinaryExpression const& node) {
|
||||
node.getLeft().emit(this);
|
||||
bool CppEmitter::emit(BinaryExpression const& node) {
|
||||
GUARDED(node.getLeft().emit(this));
|
||||
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);
|
||||
|
||||
stream << ' ' << node.getOperator() << ' ';
|
||||
if (braces) stream << "(";
|
||||
node.getLeft().emit(this);
|
||||
GUARDED(node.getLeft().emit(this));
|
||||
if (braces) stream << ")";
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,34 +31,34 @@ class CppEmitter: public Emitter {
|
|||
public:
|
||||
CppEmitter(std::ostream *stream): stream(*stream), indent_chars(0) {}
|
||||
|
||||
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(Branch const&) override;
|
||||
virtual void emit(Function const&) override;
|
||||
virtual void emit(Module const&) override;
|
||||
virtual void emit(Program const&) override;
|
||||
virtual bool emit(Return const&) override;
|
||||
virtual bool emit(Loop const&) override;
|
||||
virtual bool emit(VarDeclaration const&) override;
|
||||
virtual bool emit(Assignment const&) override;
|
||||
virtual bool emit(Print const&) override;
|
||||
virtual bool emit(Input const&) override;
|
||||
virtual bool emit(Abort const&) override;
|
||||
virtual bool emit(Assert const&) override;
|
||||
virtual bool emit(Branch const&) override;
|
||||
virtual bool emit(Function const&) override;
|
||||
virtual bool emit(Module const&) override;
|
||||
virtual bool emit(Program const&) override;
|
||||
|
||||
virtual void emit(FunctionCall const&) override;
|
||||
virtual void emit(Id const&) override;
|
||||
virtual void emit(Integer const&) override;
|
||||
virtual void emit(Float const&) override;
|
||||
virtual void emit(BinaryExpression const&) override;
|
||||
virtual bool emit(FunctionCall const&) override;
|
||||
virtual bool emit(Id const&) override;
|
||||
virtual bool emit(Integer const&) override;
|
||||
virtual bool emit(Float const&) override;
|
||||
virtual bool emit(BinaryExpression const&) override;
|
||||
|
||||
private:
|
||||
void emitIndent();
|
||||
void emitFunctionSignature(Function const& function);
|
||||
void emitFunctionParams(PointerList<FunArg> const& funargs);
|
||||
void emitFunctionArglist(PointerList<Expression> const& args);
|
||||
void emitStatements(PointerList<Statement> const& node);
|
||||
void emitBranchCondition(SemiExpression const& node);
|
||||
void emitBranchCase(BranchCase const& node);
|
||||
void emitMain(Function const& main);
|
||||
bool emitIndent();
|
||||
bool emitFunctionSignature(Function const& function);
|
||||
bool emitFunctionParams(PointerList<FunArg> const& funargs);
|
||||
bool emitFunctionArglist(PointerList<Expression> const& args);
|
||||
bool emitStatements(PointerList<Statement> const& node);
|
||||
bool emitBranchCondition(SemiExpression const& node);
|
||||
bool emitBranchCase(BranchCase const& node);
|
||||
bool emitMain(Function const& main);
|
||||
|
||||
void indent();
|
||||
void dedent();
|
||||
|
|
34
Emitter.hpp
34
Emitter.hpp
|
@ -45,24 +45,24 @@ class BinaryExpression;
|
|||
|
||||
class Emitter {
|
||||
public:
|
||||
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(Branch const&) = 0;
|
||||
virtual void emit(Function const&) = 0;
|
||||
virtual void emit(Module const&) = 0;
|
||||
virtual void emit(Program const&) = 0;
|
||||
virtual bool emit(Return const&) = 0;
|
||||
virtual bool emit(Loop const&) = 0;
|
||||
virtual bool emit(VarDeclaration const&) = 0;
|
||||
virtual bool emit(Assignment const&) = 0;
|
||||
virtual bool emit(Print const&) = 0;
|
||||
virtual bool emit(Input const&) = 0;
|
||||
virtual bool emit(Abort const&) = 0;
|
||||
virtual bool emit(Assert const&) = 0;
|
||||
virtual bool emit(Branch const&) = 0;
|
||||
virtual bool emit(Function const&) = 0;
|
||||
virtual bool emit(Module const&) = 0;
|
||||
virtual bool emit(Program const&) = 0;
|
||||
|
||||
virtual void emit(Id const&) = 0;
|
||||
virtual void emit(Integer const&) = 0;
|
||||
virtual void emit(Float const&) = 0;
|
||||
virtual void emit(FunctionCall const&) = 0;
|
||||
virtual void emit(BinaryExpression const&) = 0;
|
||||
virtual bool emit(Id const&) = 0;
|
||||
virtual bool emit(Integer const&) = 0;
|
||||
virtual bool emit(Float const&) = 0;
|
||||
virtual bool emit(FunctionCall const&) = 0;
|
||||
virtual bool emit(BinaryExpression const&) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
83
Nodes.hpp
83
Nodes.hpp
|
@ -50,22 +50,15 @@ enum class Operator {
|
|||
class Emittable {
|
||||
public:
|
||||
virtual ~Emittable() {}
|
||||
virtual void emit(Emitter *emitter) const = 0;
|
||||
virtual bool emit(Emitter *emitter) const = 0;
|
||||
};
|
||||
|
||||
|
||||
class Statement: public Emittable {
|
||||
public:
|
||||
virtual void emit(Emitter *) const {}
|
||||
};
|
||||
class Statement: public Emittable {};
|
||||
|
||||
class Expression: public Emittable {
|
||||
public:
|
||||
virtual void emit(Emitter *) const {}
|
||||
};
|
||||
class Expression: public Emittable {};
|
||||
|
||||
class SimpleExpression: public Expression {
|
||||
};
|
||||
class SimpleExpression: public Expression {};
|
||||
|
||||
class SemiExpression {
|
||||
public:
|
||||
|
@ -89,8 +82,8 @@ class Id: public SimpleExpression {
|
|||
public:
|
||||
explicit Id(std::string *c): value(c) {}
|
||||
|
||||
virtual void emit(Emitter *emitter) const {
|
||||
emitter->emit(*this);
|
||||
virtual bool emit(Emitter *emitter) const {
|
||||
return emitter->emit(*this);
|
||||
}
|
||||
|
||||
std::string const& getValue() const {
|
||||
|
@ -109,8 +102,8 @@ class Integer: public Number {
|
|||
public:
|
||||
Integer(long i): value(i) {}
|
||||
|
||||
virtual void emit(Emitter *emitter) const {
|
||||
emitter->emit(*this);
|
||||
virtual bool emit(Emitter *emitter) const {
|
||||
return emitter->emit(*this);
|
||||
}
|
||||
|
||||
long getValue() const {
|
||||
|
@ -126,8 +119,8 @@ class Float: public Number {
|
|||
public:
|
||||
Float(double f): value(f) {}
|
||||
|
||||
virtual void emit(Emitter *emitter) const {
|
||||
emitter->emit(*this);
|
||||
virtual bool emit(Emitter *emitter) const {
|
||||
return emitter->emit(*this);
|
||||
}
|
||||
|
||||
double getValue() const {
|
||||
|
@ -143,8 +136,8 @@ class Return: public Statement {
|
|||
public:
|
||||
explicit Return(Expression *e): expression(e) {}
|
||||
|
||||
virtual void emit(Emitter *emitter) const {
|
||||
emitter->emit(*this);
|
||||
virtual bool emit(Emitter *emitter) const {
|
||||
return emitter->emit(*this);
|
||||
}
|
||||
|
||||
boost::optional<Expression const&> getExpression() const {
|
||||
|
@ -160,8 +153,8 @@ class Loop: public Statement {
|
|||
public:
|
||||
Loop(PointerList<Statement> *b, Expression *c): body(b), condition(c) {}
|
||||
|
||||
virtual void emit(Emitter *emitter) const {
|
||||
emitter->emit(*this);
|
||||
virtual bool emit(Emitter *emitter) const {
|
||||
return emitter->emit(*this);
|
||||
}
|
||||
|
||||
PointerList<Statement> const& getBody() const {
|
||||
|
@ -183,8 +176,8 @@ public:
|
|||
VarDeclaration(Id *n, Type t, bool p, Expression *i):
|
||||
name(n), point(p), init(i), type(t) {}
|
||||
|
||||
virtual void emit(Emitter *emitter) const {
|
||||
emitter->emit(*this);
|
||||
virtual bool emit(Emitter *emitter) const {
|
||||
return emitter->emit(*this);
|
||||
}
|
||||
|
||||
Id const& getId() const {
|
||||
|
@ -215,8 +208,8 @@ class Assignment: public Statement {
|
|||
public:
|
||||
Assignment(Id *n, Expression *v): name(n), value(v) {}
|
||||
|
||||
virtual void emit(Emitter *emitter) const {
|
||||
emitter->emit(*this);
|
||||
virtual bool emit(Emitter *emitter) const {
|
||||
return emitter->emit(*this);
|
||||
}
|
||||
|
||||
Id const& getName() const {
|
||||
|
@ -237,8 +230,8 @@ class Print: public Statement {
|
|||
public:
|
||||
explicit Print(Expression *e): expression(e) {}
|
||||
|
||||
virtual void emit(Emitter *emitter) const {
|
||||
emitter->emit(*this);
|
||||
virtual bool emit(Emitter *emitter) const {
|
||||
return emitter->emit(*this);
|
||||
}
|
||||
|
||||
Expression const& getExpression() const {
|
||||
|
@ -254,8 +247,8 @@ class Input: public Statement {
|
|||
public:
|
||||
explicit Input(Id *v): variable(v) {}
|
||||
|
||||
virtual void emit(Emitter *emitter) const {
|
||||
emitter->emit(*this);
|
||||
virtual bool emit(Emitter *emitter) const {
|
||||
return emitter->emit(*this);
|
||||
}
|
||||
|
||||
Id const& getVariable() const {
|
||||
|
@ -269,8 +262,8 @@ private:
|
|||
|
||||
class Abort: public Statement {
|
||||
public:
|
||||
virtual void emit(Emitter *emitter) const {
|
||||
emitter->emit(*this);
|
||||
virtual bool emit(Emitter *emitter) const {
|
||||
return emitter->emit(*this);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -279,8 +272,8 @@ class Assert: public Statement {
|
|||
public:
|
||||
explicit Assert(Expression *e): expression(e) {}
|
||||
|
||||
virtual void emit(Emitter *emitter) const {
|
||||
emitter->emit(*this);
|
||||
virtual bool emit(Emitter *emitter) const {
|
||||
return emitter->emit(*this);
|
||||
}
|
||||
|
||||
Expression const& getExpression() const {
|
||||
|
@ -296,8 +289,8 @@ class FunctionCall: public Statement, public Expression {
|
|||
public:
|
||||
FunctionCall(Id *n, PointerList<Expression> *a): name(n), args(a) {}
|
||||
|
||||
virtual void emit(Emitter *emitter) const {
|
||||
emitter->emit(*this);
|
||||
virtual bool emit(Emitter *emitter) const {
|
||||
return emitter->emit(*this);
|
||||
}
|
||||
|
||||
Id const& getName() const {
|
||||
|
@ -353,8 +346,8 @@ public:
|
|||
|
||||
Branch(Id *v, Branch::Body *b): var(v), body(b) {}
|
||||
|
||||
virtual void emit(Emitter *emitter) const {
|
||||
emitter->emit(*this);
|
||||
virtual bool emit(Emitter *emitter) const {
|
||||
return emitter->emit(*this);
|
||||
}
|
||||
|
||||
Id const& getVar() const {
|
||||
|
@ -401,8 +394,8 @@ public:
|
|||
Function(Id *n, Type r, PointerList<FunArg> *a, PointerList<Statement> *b):
|
||||
name(n), type(r), args(a), body(b) {}
|
||||
|
||||
virtual void emit(Emitter *emitter) const {
|
||||
emitter->emit(*this);
|
||||
virtual bool emit(Emitter *emitter) const {
|
||||
return emitter->emit(*this);
|
||||
}
|
||||
|
||||
Id const& getName() const {
|
||||
|
@ -437,8 +430,8 @@ public:
|
|||
|
||||
Module(const std::string &n, Type s): name(n), type(s) {}
|
||||
|
||||
virtual void emit(Emitter *emitter) const {
|
||||
emitter->emit(*this);
|
||||
virtual bool emit(Emitter *emitter) const {
|
||||
return emitter->emit(*this);
|
||||
}
|
||||
|
||||
bool operator==(const Module &other) const noexcept {
|
||||
|
@ -480,8 +473,8 @@ namespace monicelli {
|
|||
|
||||
class Program: public Emittable {
|
||||
public:
|
||||
virtual void emit(Emitter *emitter) const {
|
||||
emitter->emit(*this);
|
||||
virtual bool emit(Emitter *emitter) const {
|
||||
return emitter->emit(*this);
|
||||
}
|
||||
|
||||
void setMain(Function *m) {
|
||||
|
@ -521,8 +514,8 @@ public:
|
|||
BinaryExpression(Expression *l, Operator op, Expression *r):
|
||||
left(l), op(op), right(r) {}
|
||||
|
||||
virtual void emit(Emitter *emitter) const {
|
||||
emitter->emit(*this);
|
||||
virtual bool emit(Emitter *emitter) const {
|
||||
return emitter->emit(*this);
|
||||
}
|
||||
|
||||
Expression const& getLeft() const {
|
||||
|
|
Reference in New Issue
Block a user