diff --git a/README.md b/README.md index 9a5efd5..4a6106c 100644 --- a/README.md +++ b/README.md @@ -86,8 +86,8 @@ in place of the simple `llc` compilation step. See `opt` documentation for a comprehensive list of optimizations available. ###C++ transpiler -`mcc` can be configured as a source to source compiler, which reads Monicelli -and outputs a subset of C++. +`mcc` also works as a source to source compiler, which reads Monicelli +and outputs a subset of C++. Use the option `--c++` or `-+` for that. A good way to learn on the field is comparing the resulting C++ with the input. Well, mostly with the beautified version of the input, `*.beauty.mc`. diff --git a/src/CLineParser.cpp b/src/CLineParser.cpp index 2efb692..f82abb5 100644 --- a/src/CLineParser.cpp +++ b/src/CLineParser.cpp @@ -50,6 +50,7 @@ void monicelli::parseCommandLine(int argc, char **argv) { desc.add_options() ("help,h", "display this help message") ("version,v", "display version") + ("c++,+", "emit C++ source code instead of LLVM bitcode") ("input,i", po::value>(), "input files to process") ; diff --git a/src/main.cpp b/src/main.cpp index 907d697..e7d42b8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -35,28 +35,52 @@ #include #include #include -#include +#include using namespace monicelli; +boost::regex NAME_RE("^(.+)\\.mc$"); +boost::regex MODULE_RE("^(.+)\\.mm$"); + +int process(std::string const&, std::function); + int main(int argc, char **argv) { parseCommandLine(argc, argv); - - if (!configHas("input")) return 0; - registerStdLib(getModuleRegistry()); - boost::regex namere("^(.+)\\.mc$"); - boost::regex modulere("^(.+)\\.mm$"); + if (!configHas("input")) { + std::cerr << "No input." << std::endl; + return 0; + } + if (configHas("c++")) { + return process("cpp", [](std::ostream &outstream, Program *program) { + CppEmitter emitter(&outstream); + if (!program->emit(&emitter)) return false; + return true; + }); + } else { + return process("bc", [](std::ostream & outstream, Program *program) { + BitcodeEmitter emitter; + if (!program->emit(&emitter)) return false; + + llvm::raw_os_ostream stream(outstream); + llvm::WriteBitcodeToFile(&emitter.getModule(), stream); + + return true; + }); + } +} + +int process(std::string const& suffix, std::function writer) { std::vector sources; std::vector modules; for (std::string const& arg: config>("input")) { - if (boost::regex_match(arg, namere)) { + if (boost::regex_match(arg, NAME_RE)) { sources.push_back(arg); - } else if (boost::regex_match(arg, modulere)) { + } else if (boost::regex_match(arg, MODULE_RE)) { modules.push_back(arg); } } @@ -71,7 +95,6 @@ int main(int argc, char **argv) { Program program; Scanner scanner(&instream); Parser parser(scanner, program); - BitcodeEmitter emitter; # if YYDEBUG parser.set_debug_level(1); @@ -81,17 +104,17 @@ int main(int argc, char **argv) { std::string outputname = boost::filesystem::path(name).filename().native(); - if (boost::regex_match(outputname, namere)) { - outputname = boost::regex_replace(outputname, namere, "$1.bc"); + if (boost::regex_match(outputname, NAME_RE)) { + outputname = boost::regex_replace(outputname, NAME_RE, "$1." + suffix); } else { - outputname = outputname + ".bc"; + outputname = outputname + '.' + suffix; } - if (!program.emit(&emitter)) return 1; - std::ofstream outstream(outputname); - llvm::raw_os_ostream stream(outstream); - llvm::WriteBitcodeToFile(&emitter.getModule(), stream); + + if (!writer(outstream, &program)) return 1; } + + return 0; }