Introducing boost::ptr_vector and boost::ptr_unordered_set.
This is an easy way to increase the uniformity of the API.
This commit is contained in:
parent
19a0c656f2
commit
b2e7a11b7a
|
@ -254,8 +254,8 @@ bool BitcodeEmitter::emit(Loop const& node) {
|
||||||
d->builder.SetInsertPoint(body);
|
d->builder.SetInsertPoint(body);
|
||||||
|
|
||||||
d->scope.enter();
|
d->scope.enter();
|
||||||
for (Statement const* statement: node.getBody()) {
|
for (Statement const& statement: node.getBody()) {
|
||||||
GUARDED(statement->emit(this));
|
GUARDED(statement.emit(this));
|
||||||
}
|
}
|
||||||
d->scope.leave();
|
d->scope.leave();
|
||||||
|
|
||||||
|
@ -424,8 +424,8 @@ bool BitcodeEmitter::emit(FunctionCall const& node) {
|
||||||
|
|
||||||
auto param = callee->getArgumentList().begin();
|
auto param = callee->getArgumentList().begin();
|
||||||
std::vector<llvm::Value*> callargs;
|
std::vector<llvm::Value*> callargs;
|
||||||
for (Expression const* arg: node.getArgs()) {
|
for (Expression const& arg: node.getArgs()) {
|
||||||
GUARDED(arg->emit(this));
|
GUARDED(arg.emit(this));
|
||||||
callargs.push_back(coerce(d, d->retval, param->getType()));
|
callargs.push_back(coerce(d, d->retval, param->getType()));
|
||||||
++param;
|
++param;
|
||||||
}
|
}
|
||||||
|
@ -449,17 +449,17 @@ bool BitcodeEmitter::emit(Branch const& node) {
|
||||||
getGlobalContext(), "endif"
|
getGlobalContext(), "endif"
|
||||||
);
|
);
|
||||||
|
|
||||||
BranchCase const* last = body.getCases().back();
|
BranchCase const& last = body.getCases().back();
|
||||||
|
|
||||||
for (BranchCase const* cas: body.getCases()) {
|
for (BranchCase const& cas: body.getCases()) {
|
||||||
emitSemiExpression(node.getVar(), cas->getCondition());
|
emitSemiExpression(node.getVar(), cas.getCondition());
|
||||||
d->builder.CreateCondBr(
|
d->builder.CreateCondBr(
|
||||||
isTrue(d->builder, d->retval, "condition"), thenbb, elsebb
|
isTrue(d->builder, d->retval, "condition"), thenbb, elsebb
|
||||||
);
|
);
|
||||||
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()) {
|
||||||
GUARDED(statement->emit(this));
|
GUARDED(statement.emit(this));
|
||||||
}
|
}
|
||||||
d->scope.leave();
|
d->scope.leave();
|
||||||
d->builder.CreateBr(mergebb);
|
d->builder.CreateBr(mergebb);
|
||||||
|
@ -467,7 +467,7 @@ bool BitcodeEmitter::emit(Branch const& node) {
|
||||||
func->getBasicBlockList().push_back(elsebb);
|
func->getBasicBlockList().push_back(elsebb);
|
||||||
d->builder.SetInsertPoint(elsebb);
|
d->builder.SetInsertPoint(elsebb);
|
||||||
|
|
||||||
if (cas != last) {
|
if (&cas != &last) {
|
||||||
thenbb = llvm::BasicBlock::Create(getGlobalContext(), "then", func);
|
thenbb = llvm::BasicBlock::Create(getGlobalContext(), "then", func);
|
||||||
elsebb = llvm::BasicBlock::Create(getGlobalContext(), "else");
|
elsebb = llvm::BasicBlock::Create(getGlobalContext(), "else");
|
||||||
}
|
}
|
||||||
|
@ -475,8 +475,8 @@ bool 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()) {
|
||||||
GUARDED(statement->emit(this));
|
GUARDED(statement.emit(this));
|
||||||
}
|
}
|
||||||
d->scope.leave();
|
d->scope.leave();
|
||||||
d->builder.CreateBr(mergebb);
|
d->builder.CreateBr(mergebb);
|
||||||
|
@ -491,13 +491,13 @@ bool BitcodeEmitter::emit(Branch const& node) {
|
||||||
bool BitcodeEmitter::emit(FunctionPrototype const& node) {
|
bool BitcodeEmitter::emit(FunctionPrototype const& node) {
|
||||||
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;
|
std::unordered_set<std::string> argsSet;
|
||||||
for (FunArg const* arg: node.getArgs()) {
|
for (FunArg const& arg: node.getArgs()) {
|
||||||
std::string const& name = arg->getName().getValue();
|
std::string const& name = arg.getName().getValue();
|
||||||
if (argsSet.find(name) != argsSet.end()) {
|
if (argsSet.find(name) != argsSet.end()) {
|
||||||
return reportError({
|
return reportError({
|
||||||
"Two arguments with same name to function",
|
"Two arguments with same name to function",
|
||||||
|
@ -536,8 +536,8 @@ bool BitcodeEmitter::emit(FunctionPrototype const& node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto argToEmit = func->arg_begin();
|
auto argToEmit = func->arg_begin();
|
||||||
for (FunArg const* arg: node.getArgs()) {
|
for (FunArg const& arg: node.getArgs()) {
|
||||||
argToEmit->setName(arg->getName().getValue());
|
argToEmit->setName(arg.getName().getValue());
|
||||||
++argToEmit;
|
++argToEmit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -558,16 +558,16 @@ bool BitcodeEmitter::emit(Function const& node) {
|
||||||
d->builder.SetInsertPoint(bb);
|
d->builder.SetInsertPoint(bb);
|
||||||
|
|
||||||
auto argToAlloc = func->arg_begin();
|
auto argToAlloc = func->arg_begin();
|
||||||
for (FunArg const* arg: node.getPrototype().getArgs()) {
|
for (FunArg const& arg: node.getPrototype().getArgs()) {
|
||||||
llvm::AllocaInst *alloc = allocateVar(
|
llvm::AllocaInst *alloc = allocateVar(
|
||||||
func, arg->getName(), LLVMType(arg->getType())
|
func, arg.getName(), LLVMType(arg.getType())
|
||||||
);
|
);
|
||||||
d->builder.CreateStore(argToAlloc, alloc);
|
d->builder.CreateStore(argToAlloc, alloc);
|
||||||
d->scope.push(arg->getName().getValue(), alloc);
|
d->scope.push(arg.getName().getValue(), alloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Statement const* stat: node.getBody()) {
|
for (Statement const& stat: node.getBody()) {
|
||||||
GUARDED(stat->emit(this));
|
GUARDED(stat.emit(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
verifyFunction(*func);
|
verifyFunction(*func);
|
||||||
|
@ -583,12 +583,12 @@ bool BitcodeEmitter::emit(Module const& node) {
|
||||||
|
|
||||||
bool BitcodeEmitter::emit(Program const& program) {
|
bool BitcodeEmitter::emit(Program const& program) {
|
||||||
auto const& externals = getModuleRegistry().getRegisteredFunctions();
|
auto const& externals = getModuleRegistry().getRegisteredFunctions();
|
||||||
for (FunctionPrototype const* proto: externals) {
|
for (FunctionPrototype const& proto: externals) {
|
||||||
GUARDED(proto->emit(this));
|
GUARDED(proto.emit(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Function const* function: program.getFunctions()) {
|
for (Function const& function: program.getFunctions()) {
|
||||||
GUARDED(function->emit(this));
|
GUARDED(function.emit(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (program.getMain()) {
|
if (program.getMain()) {
|
||||||
|
|
|
@ -58,8 +58,8 @@ bool CppEmitter::emit(Program const& program) {
|
||||||
stream << "\n";
|
stream << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Function *function: program.getFunctions()) {
|
for (Function const& function: program.getFunctions()) {
|
||||||
emit(function->getPrototype());
|
emit(function.getPrototype());
|
||||||
stream << ";\n";
|
stream << ";\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,8 +67,8 @@ bool CppEmitter::emit(Program const& program) {
|
||||||
stream << "\n";
|
stream << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Function *function: program.getFunctions()) {
|
for (Function const& function: program.getFunctions()) {
|
||||||
GUARDED(function->emit(this));
|
GUARDED(function.emit(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (program.getMain()) {
|
if (program.getMain()) {
|
||||||
|
@ -79,9 +79,9 @@ bool CppEmitter::emit(Program const& program) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CppEmitter::emitStatements(PointerList<Statement> const& node) {
|
bool CppEmitter::emitStatements(PointerList<Statement> const& node) {
|
||||||
for (Statement *s: node) {
|
for (Statement const& s: node) {
|
||||||
emitIndent();
|
emitIndent();
|
||||||
GUARDED(s->emit(this));
|
GUARDED(s.emit(this));
|
||||||
stream << STATEMENT_TERMINATOR;
|
stream << STATEMENT_TERMINATOR;
|
||||||
}
|
}
|
||||||
return stream;
|
return stream;
|
||||||
|
@ -202,10 +202,10 @@ bool CppEmitter::emit(Branch const& branch) {
|
||||||
GUARDED(var.emit(this));
|
GUARDED(var.emit(this));
|
||||||
|
|
||||||
if (body.getCases().size() > 0) {
|
if (body.getCases().size() > 0) {
|
||||||
BranchCase *last = body.getCases().back();
|
BranchCase const& last = body.getCases().back();
|
||||||
for (BranchCase *cas: body.getCases()) {
|
for (BranchCase const& cas: body.getCases()) {
|
||||||
emitBranchCase(*cas);
|
emitBranchCase(cas);
|
||||||
if (cas != last) {
|
if (&cas != &last) {
|
||||||
stream << " else if (";
|
stream << " else if (";
|
||||||
GUARDED(var.emit(this));
|
GUARDED(var.emit(this));
|
||||||
}
|
}
|
||||||
|
@ -236,10 +236,10 @@ bool CppEmitter::emit(Assignment const& assignment) {
|
||||||
|
|
||||||
|
|
||||||
bool CppEmitter::emitFunctionArglist(PointerList<Expression> const& args) {
|
bool CppEmitter::emitFunctionArglist(PointerList<Expression> const& args) {
|
||||||
Expression *last = args.back();
|
Expression const& last = args.back();
|
||||||
for (Expression const* arg: args) {
|
for (Expression const& arg: args) {
|
||||||
GUARDED(arg->emit(this));
|
GUARDED(arg.emit(this));
|
||||||
if (arg != last) {
|
if (&arg != &last) {
|
||||||
stream << ", ";
|
stream << ", ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -297,12 +297,12 @@ std::ostream& operator<<(std::ostream &stream, Type const& type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CppEmitter::emitFunctionParams(PointerList<FunArg> const& funargs) {
|
bool CppEmitter::emitFunctionParams(PointerList<FunArg> const& funargs) {
|
||||||
FunArg *last = funargs.back();
|
FunArg const& last = funargs.back();
|
||||||
|
|
||||||
for (FunArg const* funarg: funargs) {
|
for (FunArg const& funarg: funargs) {
|
||||||
stream << funarg->getType() << (funarg->isPointer()? "* ": " ");
|
stream << funarg.getType() << (funarg.isPointer()? "* ": " ");
|
||||||
GUARDED(funarg->getName().emit(this));
|
GUARDED(funarg.getName().emit(this));
|
||||||
if (funarg != last) {
|
if (&funarg != &last) {
|
||||||
stream << ", ";
|
stream << ", ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ModuleRegistry.hpp"
|
#include "ModuleRegistry.hpp"
|
||||||
|
#include "Pointers.hpp"
|
||||||
#include "Nodes.hpp"
|
#include "Nodes.hpp"
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
using namespace monicelli;
|
using namespace monicelli;
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ ModuleRegistry& monicelli::getModuleRegistry() {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ModuleRegistry::Private {
|
struct ModuleRegistry::Private {
|
||||||
PointerList<FunctionPrototype> prototypes;
|
boost::ptr_unordered_set<FunctionPrototype> prototypes;
|
||||||
};
|
};
|
||||||
|
|
||||||
ModuleRegistry::ModuleRegistry() {
|
ModuleRegistry::ModuleRegistry() {
|
||||||
|
@ -42,20 +42,20 @@ ModuleRegistry::~ModuleRegistry() {
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
PointerList<FunctionPrototype> const& ModuleRegistry::getRegisteredFunctions() const {
|
PointerSet<FunctionPrototype> const& ModuleRegistry::getRegisteredFunctions() const {
|
||||||
return d->prototypes;
|
return d->prototypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModuleRegistry::registerFunction(FunctionPrototype *proto) {
|
void ModuleRegistry::registerFunction(FunctionPrototype *proto) {
|
||||||
d->prototypes.push_back(proto);
|
d->prototypes.insert(proto);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PUT(type, funcname) \
|
#define PUT(type, funcname) \
|
||||||
new FunctionPrototype { \
|
new FunctionPrototype { \
|
||||||
new Id {#funcname}, Type::VOID, \
|
new Id {#funcname}, Type::VOID, \
|
||||||
new PointerList<FunArg> { \
|
plist({ \
|
||||||
new FunArg {new Id {"value"}, type, false} \
|
new FunArg {new Id {"value"}, type, false} \
|
||||||
}, \
|
}), \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define GET(type, funcname) \
|
#define GET(type, funcname) \
|
||||||
|
@ -77,14 +77,15 @@ void monicelli::registerStdLib(ModuleRegistry &r) {
|
||||||
r.registerFunction(GET(Type::INT, __Monicelli_getInt));
|
r.registerFunction(GET(Type::INT, __Monicelli_getInt));
|
||||||
r.registerFunction(new FunctionPrototype {
|
r.registerFunction(new FunctionPrototype {
|
||||||
new Id("__Monicelli_assert"), Type::VOID,
|
new Id("__Monicelli_assert"), Type::VOID,
|
||||||
new PointerList<FunArg> {
|
plist({
|
||||||
new FunArg {new Id("condition"), Type::CHAR, false}
|
new FunArg {new Id("condition"), Type::CHAR, false}
|
||||||
}
|
})
|
||||||
});
|
});
|
||||||
r.registerFunction(new FunctionPrototype {
|
r.registerFunction(new FunctionPrototype {
|
||||||
new Id("__Monicelli_abort"), Type::VOID,
|
new Id("__Monicelli_abort"), Type::VOID,
|
||||||
new PointerList<FunArg> {}
|
new PointerList<FunArg> {}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef PUT
|
#undef PUT
|
||||||
|
|
|
@ -32,7 +32,7 @@ public:
|
||||||
ModuleRegistry(ModuleRegistry&) = delete;
|
ModuleRegistry(ModuleRegistry&) = delete;
|
||||||
virtual ~ModuleRegistry();
|
virtual ~ModuleRegistry();
|
||||||
|
|
||||||
PointerList<FunctionPrototype> const& getRegisteredFunctions() const;
|
PointerSet<FunctionPrototype> const& getRegisteredFunctions() const;
|
||||||
void registerFunction(FunctionPrototype *proto);
|
void registerFunction(FunctionPrototype *proto);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
34
Pointers.hpp
34
Pointers.hpp
|
@ -21,33 +21,25 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <initializer_list>
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
#include <boost/ptr_container/ptr_unordered_set.hpp>
|
||||||
|
#include <boost/ptr_container/ptr_vector.hpp>
|
||||||
|
|
||||||
namespace monicelli {
|
namespace monicelli {
|
||||||
|
|
||||||
// We need these instead of an using decl for compatibility
|
template<typename T> using Pointer = std::unique_ptr<T>;
|
||||||
template <class T>
|
template<typename T> using PointerList = boost::ptr_vector<T>;
|
||||||
class Pointer: public std::unique_ptr<T> {
|
template<typename T> using PointerSet = boost::ptr_unordered_set<T>;
|
||||||
public:
|
|
||||||
Pointer(T *p = nullptr): std::unique_ptr<T>(p) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
template<class T>
|
PointerList<T>* plist(std::initializer_list<T*> elements) {
|
||||||
class PointerList: public std::vector<T*> {
|
PointerList<T> *result = new PointerList<T>(elements.size());
|
||||||
public:
|
for (T *el: elements) {
|
||||||
using std::vector<T*>::vector;
|
result->push_back(el);
|
||||||
PointerList() {}
|
|
||||||
PointerList(PointerList&) = delete;
|
|
||||||
|
|
||||||
virtual ~PointerList() {
|
|
||||||
for (T *element: *this) {
|
|
||||||
delete element;
|
|
||||||
}
|
}
|
||||||
}
|
return result;
|
||||||
};
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in New Issue
Block a user