/* Resp: A programming language * Copyright (C) 2008-2009 David Robillard * * Resp is free software: you can redistribute it and/or modify it under * the terms of the GNU Affero General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at your * option) any later version. * * Resp 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 Affero General * Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Resp. If not, see . */ /** @file * @brief Main program */ #include #include #include #include "resp.hpp" using namespace std; GC Object::pool(8 * 1024 * 1024); int print_usage(char* name, bool error) { ostream& os = error ? cerr : cout; os << "Usage: " << name << " [OPTION]... [FILE]..." << endl; os << "Evaluate and/or compile Resp code" << endl; os << endl; os << " -h Display this help and exit" << endl; os << " -r Enter REPL after evaluating files" << endl; os << " -p Pretty-print input only" << endl; os << " -b BACKEND Use backend (llvm or c)" << endl; os << " -g Debug (disable optimisation)" << endl; os << " -d Dump generated code during compilation" << endl; os << " -S Stop after compilation (output assembler)" << endl; os << " -e EXPRESSION Evaluate EXPRESSION" << endl; os << " -o FILE Compile output to FILE (don't run)" << endl; return error ? 1 : 0; } int main(int argc, char** argv) { // Read command line arguments map args; list files; for (int i = 1; i < argc; ++i) { if (!strncmp(argv[i], "-h", 3)) { return print_usage(argv[0], false); } else if (argv[i][0] != '-') { files.push_back(argv[i]); } else if (!strncmp(argv[i], "-r", 3) || !strncmp(argv[i], "-p", 3) || !strncmp(argv[i], "-g", 3) || !strncmp(argv[i], "-d", 3) || !strncmp(argv[i], "-S", 3)) { args.insert(make_pair(argv[i], "")); } else if (i == argc-1 || argv[i+1][0] == '-') { return print_usage(argv[0], true); } else { args.insert(make_pair(argv[i], argv[i+1])); ++i; } } PEnv penv; TEnv tenv(penv); initLang(penv, tenv); Engine* engine = NULL; map::const_iterator a = args.find("-b"); const string backend_name = (a != args.end() ? a->second : "llvm"); if (backend_name == "llvm") engine = resp_new_llvm_engine(); else if (backend_name == "c") engine = resp_new_c_engine(); if (!engine) { std::cerr << "Unable to open backend " << backend_name << std::endl; return 1; } CEnv* cenv = new CEnv(penv, tenv, engine); cenv->args = args; Object::pool.lock(); int ret = 0; a = args.find("-o"); bool batch = a != args.end(); const string output = (a != args.end()) ? a->second : ""; if (args.find("-p") != args.end()) { ifstream is(files.front().c_str()); if (is.good()) { Cursor loc; AST* exp = readExpression(loc, is); AST* ast = penv.parse(exp); pprint(cout, ast); } delete cenv; return 0; } a = args.find("-e"); if (a != args.end()) { istringstream is(a->second); ret = eval(*cenv, "(command line)", is, !batch); } for (list::iterator f = files.begin(); f != files.end(); ++f) { ifstream is(f->c_str()); if (is.good()) { ret = ret | eval(*cenv, *f, is, !batch); } else { cerr << argv[0] << ": " << *f << ": " << strerror(errno) << endl; ++ret; } is.close(); } if (args.find("-r") != args.end() || (files.empty() && args.find("-e") == args.end())) ret = repl(*cenv); if (cenv->args.find("-S") != cenv->args.end() || cenv->args.find("-d") != cenv->args.end()) { ofstream fs; if (output != "") fs.open(output.c_str()); ostream& os = (output != "") ? fs : cout; if (os.good()) { cenv->engine()->writeModule(*cenv, os); } else { cerr << argv[0] << ": " << a->second << ": " << strerror(errno) << endl; ++ret; } if (output != "") fs.close(); } delete cenv; delete engine; return ret; }