Replace hardcoded stdlib prototypes with a module registry.
This commit is contained in:
parent
3aade87599
commit
b5196b1776
|
@ -20,7 +20,7 @@
|
|||
#include "BitcodeEmitter.hpp"
|
||||
#include "Scope.hpp"
|
||||
#include "Nodes.hpp"
|
||||
#include "RuntimePrototypes.hpp"
|
||||
#include "ModuleRegistry.hpp"
|
||||
|
||||
#include <llvm/IR/Verifier.h>
|
||||
#include <llvm/IR/DerivedTypes.h>
|
||||
|
@ -578,28 +578,13 @@ bool BitcodeEmitter::emit(Function const& node) {
|
|||
}
|
||||
|
||||
bool BitcodeEmitter::emit(Module const& node) {
|
||||
if (node.getType() == Module::SYSTEM) {
|
||||
auto module = STANDARD_MODULES.find(node.getName());
|
||||
|
||||
if (module == STANDARD_MODULES.end()) {
|
||||
return reportError({
|
||||
"Unknown system module", node.getName()
|
||||
});
|
||||
}
|
||||
|
||||
for (FunctionPrototype const* proto: module->second) {
|
||||
GUARDED(proto->emit(this));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO (maybe) user modules
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BitcodeEmitter::emit(Program const& program) {
|
||||
for (Module const& module: program.getModules()) {
|
||||
GUARDED(module.emit(this));
|
||||
auto const& externals = getModuleRegistry().getRegisteredFunctions();
|
||||
for (FunctionPrototype const* proto: externals) {
|
||||
GUARDED(proto->emit(this));
|
||||
}
|
||||
|
||||
for (Function const* function: program.getFunctions()) {
|
||||
|
|
|
@ -95,7 +95,7 @@ flex_target(Scanner Monicelli.lpp ${CMAKE_CURRENT_BINARY_DIR}/Lexer.cpp)
|
|||
add_flex_bison_dependency(Scanner Parser)
|
||||
|
||||
add_executable(mcc
|
||||
main.cpp Nodes.cpp
|
||||
main.cpp Nodes.cpp ModuleRegistry.cpp
|
||||
${BISON_Parser_OUTPUTS} ${FLEX_Scanner_OUTPUTS}
|
||||
CppEmitter.cpp BitcodeEmitter.cpp
|
||||
)
|
||||
|
|
91
ModuleRegistry.cpp
Normal file
91
ModuleRegistry.cpp
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* 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 "ModuleRegistry.hpp"
|
||||
#include "Nodes.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
using namespace monicelli;
|
||||
|
||||
static ModuleRegistry globalRegistry;
|
||||
|
||||
ModuleRegistry& monicelli::getModuleRegistry() {
|
||||
return globalRegistry;
|
||||
}
|
||||
|
||||
struct ModuleRegistry::Private {
|
||||
PointerList<FunctionPrototype> prototypes;
|
||||
};
|
||||
|
||||
ModuleRegistry::ModuleRegistry() {
|
||||
d = new Private;
|
||||
}
|
||||
|
||||
ModuleRegistry::~ModuleRegistry() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
PointerList<FunctionPrototype> const& ModuleRegistry::getRegisteredFunctions() const {
|
||||
return d->prototypes;
|
||||
}
|
||||
|
||||
void ModuleRegistry::registerFunction(FunctionPrototype *proto) {
|
||||
d->prototypes.push_back(proto);
|
||||
}
|
||||
|
||||
#define PUT(type, funcname) \
|
||||
new FunctionPrototype { \
|
||||
new Id {#funcname}, Type::VOID, \
|
||||
new PointerList<FunArg> { \
|
||||
new FunArg {new Id {"value"}, type, false} \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define GET(type, funcname) \
|
||||
new FunctionPrototype { \
|
||||
new Id {#funcname}, type, \
|
||||
new PointerList<FunArg> {}, \
|
||||
}
|
||||
|
||||
void monicelli::registerStdLib(ModuleRegistry &r) {
|
||||
r.registerFunction(PUT(Type::CHAR, __Monicelli_putBool));
|
||||
r.registerFunction(PUT(Type::CHAR, __Monicelli_putChar));
|
||||
r.registerFunction(PUT(Type::FLOAT, __Monicelli_putFloat));
|
||||
r.registerFunction(PUT(Type::DOUBLE, __Monicelli_putDouble));
|
||||
r.registerFunction(PUT(Type::INT, __Monicelli_putInt));
|
||||
r.registerFunction(GET(Type::CHAR, __Monicelli_getBool));
|
||||
r.registerFunction(GET(Type::CHAR, __Monicelli_getChar));
|
||||
r.registerFunction(GET(Type::FLOAT, __Monicelli_getFloat));
|
||||
r.registerFunction(GET(Type::DOUBLE, __Monicelli_getDouble));
|
||||
r.registerFunction(GET(Type::INT, __Monicelli_getInt));
|
||||
r.registerFunction(new FunctionPrototype {
|
||||
new Id("__Monicelli_assert"), Type::VOID,
|
||||
new PointerList<FunArg> {
|
||||
new FunArg {new Id("condition"), Type::CHAR, false}
|
||||
}
|
||||
});
|
||||
r.registerFunction(new FunctionPrototype {
|
||||
new Id("__Monicelli_abort"), Type::VOID,
|
||||
new PointerList<FunArg> {}
|
||||
});
|
||||
}
|
||||
|
||||
#undef PUT
|
||||
#undef GET
|
29
ModuleRegistry.hpp
Normal file
29
ModuleRegistry.hpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
#ifndef MODULE_REGISTRY_HPP
|
||||
#define MODULE_REGISTRY_HPP
|
||||
|
||||
#include "Pointers.hpp"
|
||||
|
||||
namespace monicelli {
|
||||
|
||||
class FunctionPrototype;
|
||||
|
||||
class ModuleRegistry {
|
||||
public:
|
||||
ModuleRegistry();
|
||||
ModuleRegistry(ModuleRegistry&) = delete;
|
||||
virtual ~ModuleRegistry();
|
||||
|
||||
PointerList<FunctionPrototype> const& getRegisteredFunctions() const;
|
||||
void registerFunction(FunctionPrototype *proto);
|
||||
|
||||
private:
|
||||
struct Private;
|
||||
Private *d;
|
||||
};
|
||||
|
||||
ModuleRegistry& getModuleRegistry();
|
||||
void registerStdLib(ModuleRegistry &);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,74 +0,0 @@
|
|||
#ifndef RUNTIME_PROTOTYPES_HPP
|
||||
#define RUNTIME_PROTOTYPES_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 "Nodes.hpp"
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#define PUT(type, funcname) \
|
||||
new FunctionPrototype { \
|
||||
new Id {#funcname}, Type::VOID, \
|
||||
new PointerList<FunArg> { \
|
||||
new FunArg {new Id {"value"}, type, false} \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define GET(type, funcname) \
|
||||
new FunctionPrototype { \
|
||||
new Id {#funcname}, type, \
|
||||
new PointerList<FunArg> {}, \
|
||||
}
|
||||
|
||||
namespace monicelli {
|
||||
|
||||
static const std::map<std::string, std::vector<FunctionPrototype const*>> STANDARD_MODULES = {
|
||||
{"iostream", {
|
||||
PUT(Type::CHAR, __Monicelli_putBool),
|
||||
PUT(Type::CHAR, __Monicelli_putChar),
|
||||
PUT(Type::FLOAT, __Monicelli_putFloat),
|
||||
PUT(Type::DOUBLE, __Monicelli_putDouble),
|
||||
PUT(Type::INT, __Monicelli_putInt),
|
||||
GET(Type::CHAR, __Monicelli_getBool),
|
||||
GET(Type::CHAR, __Monicelli_getChar),
|
||||
GET(Type::FLOAT, __Monicelli_getFloat),
|
||||
GET(Type::DOUBLE, __Monicelli_getDouble),
|
||||
GET(Type::INT, __Monicelli_getInt)
|
||||
}},
|
||||
{"cassert", { new FunctionPrototype {
|
||||
new Id("__Monicelli_assert"), Type::VOID,
|
||||
new PointerList<FunArg> {
|
||||
new FunArg {new Id("condition"), Type::CHAR, false}
|
||||
},
|
||||
}}},
|
||||
{"cstdlib", { new FunctionPrototype {
|
||||
new Id("__Monicelli_abort"), Type::VOID,
|
||||
new PointerList<FunArg> {},
|
||||
}}}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#undef PUT
|
||||
#undef GET
|
||||
|
||||
#endif
|
3
main.cpp
3
main.cpp
|
@ -20,6 +20,7 @@
|
|||
#include "Scanner.hpp"
|
||||
#include "Parser.hpp"
|
||||
#include "CppEmitter.hpp"
|
||||
#include "ModuleRegistry.hpp"
|
||||
#include "BitcodeEmitter.hpp"
|
||||
|
||||
#include <llvm/Bitcode/ReaderWriter.h>
|
||||
|
@ -38,6 +39,8 @@ using namespace monicelli;
|
|||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
registerStdLib(getModuleRegistry());
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
std::string inputname(argv[i]);
|
||||
std::ifstream instream(inputname);
|
||||
|
|
Reference in New Issue
Block a user