From b5196b17765956ee3d4da70d0a130170bfae47d9 Mon Sep 17 00:00:00 2001 From: Stefano Sanfilippo Date: Sun, 8 Mar 2015 13:25:59 +0100 Subject: [PATCH] Replace hardcoded stdlib prototypes with a module registry. --- BitcodeEmitter.cpp | 23 ++--------- CMakeLists.txt | 2 +- ModuleRegistry.cpp | 91 +++++++++++++++++++++++++++++++++++++++++++ ModuleRegistry.hpp | 29 ++++++++++++++ RuntimePrototypes.hpp | 74 ----------------------------------- main.cpp | 3 ++ 6 files changed, 128 insertions(+), 94 deletions(-) create mode 100644 ModuleRegistry.cpp create mode 100644 ModuleRegistry.hpp delete mode 100644 RuntimePrototypes.hpp diff --git a/BitcodeEmitter.cpp b/BitcodeEmitter.cpp index 2174ec0..654946d 100644 --- a/BitcodeEmitter.cpp +++ b/BitcodeEmitter.cpp @@ -20,7 +20,7 @@ #include "BitcodeEmitter.hpp" #include "Scope.hpp" #include "Nodes.hpp" -#include "RuntimePrototypes.hpp" +#include "ModuleRegistry.hpp" #include #include @@ -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()) { diff --git a/CMakeLists.txt b/CMakeLists.txt index 3867919..d413a97 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 ) diff --git a/ModuleRegistry.cpp b/ModuleRegistry.cpp new file mode 100644 index 0000000..6a2e4d3 --- /dev/null +++ b/ModuleRegistry.cpp @@ -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 . + */ + +#include "ModuleRegistry.hpp" +#include "Nodes.hpp" + +#include + +using namespace monicelli; + +static ModuleRegistry globalRegistry; + +ModuleRegistry& monicelli::getModuleRegistry() { + return globalRegistry; +} + +struct ModuleRegistry::Private { + PointerList prototypes; +}; + +ModuleRegistry::ModuleRegistry() { + d = new Private; +} + +ModuleRegistry::~ModuleRegistry() { + delete d; +} + +PointerList 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 { \ + new FunArg {new Id {"value"}, type, false} \ + }, \ + } + +#define GET(type, funcname) \ + new FunctionPrototype { \ + new Id {#funcname}, type, \ + new PointerList {}, \ + } + +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 { + new FunArg {new Id("condition"), Type::CHAR, false} + } + }); + r.registerFunction(new FunctionPrototype { + new Id("__Monicelli_abort"), Type::VOID, + new PointerList {} + }); +} + +#undef PUT +#undef GET diff --git a/ModuleRegistry.hpp b/ModuleRegistry.hpp new file mode 100644 index 0000000..1598269 --- /dev/null +++ b/ModuleRegistry.hpp @@ -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 const& getRegisteredFunctions() const; + void registerFunction(FunctionPrototype *proto); + +private: + struct Private; + Private *d; +}; + +ModuleRegistry& getModuleRegistry(); +void registerStdLib(ModuleRegistry &); + +} + +#endif diff --git a/RuntimePrototypes.hpp b/RuntimePrototypes.hpp deleted file mode 100644 index 9c8e744..0000000 --- a/RuntimePrototypes.hpp +++ /dev/null @@ -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 . - */ - -#include "Nodes.hpp" -#include -#include -#include - -#define PUT(type, funcname) \ - new FunctionPrototype { \ - new Id {#funcname}, Type::VOID, \ - new PointerList { \ - new FunArg {new Id {"value"}, type, false} \ - }, \ - } - -#define GET(type, funcname) \ - new FunctionPrototype { \ - new Id {#funcname}, type, \ - new PointerList {}, \ - } - -namespace monicelli { - -static const std::map> 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 { - new FunArg {new Id("condition"), Type::CHAR, false} - }, - }}}, - {"cstdlib", { new FunctionPrototype { - new Id("__Monicelli_abort"), Type::VOID, - new PointerList {}, - }}} -}; - -} - -#undef PUT -#undef GET - -#endif diff --git a/main.cpp b/main.cpp index 1b94c3c..293a9c3 100644 --- a/main.cpp +++ b/main.cpp @@ -20,6 +20,7 @@ #include "Scanner.hpp" #include "Parser.hpp" #include "CppEmitter.hpp" +#include "ModuleRegistry.hpp" #include "BitcodeEmitter.hpp" #include @@ -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);