diff options
-rw-r--r-- | ack.tpr | 2 | ||||
-rw-r--r-- | tuplr.cpp | 87 | ||||
-rw-r--r-- | tuplr.hpp | 13 | ||||
-rw-r--r-- | tuplr_llvm.cpp | 91 |
4 files changed, 144 insertions, 49 deletions
@@ -4,5 +4,5 @@ (= 0 n) (ack (- m 1) 1) (ack (- m 1) (ack m (- n 1)))))) -(ack 3 12) +(ack 3 10) @@ -15,6 +15,11 @@ * along with Tuplr. If not, see <http://www.gnu.org/licenses/>. */ +#include <cerrno> +#include <cstring> +#include <fstream> +#include <set> +#include <sstream> #include <stack> #include "tuplr.hpp" @@ -88,3 +93,85 @@ readExpression(Cursor& cur, std::istream& in) return SExp(cur); } + +/*************************************************************************** + * EVAL/REPL/MAIN * + ***************************************************************************/ + +int +print_usage(char* name, bool error) +{ + std::ostream& os = error ? std::cerr : std::cout; + os << "Usage: " << name << " [OPTION]... [FILE]..." << endl; + os << "Evaluate and/or compile Tuplr code" << endl; + os << endl; + os << " -h Display this help and exit" << endl; + os << " -r Enter REPL after evaluating files" << endl; + os << " -e EXPRESSION Evaluate EXPRESSION" << endl; + os << " -o FILE Write assembly output to FILE" << endl; + return error ? 1 : 0; +} + +int +main(int argc, char** argv) +{ + PEnv penv; + TEnv tenv(penv); + initLang(penv, tenv); + + CEnv* cenv = newCenv(penv, tenv); + + map<string,string> args; + list<string> 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)) { + 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; + } + } + + int ret = 0; + map<string,string>::iterator a = args.find("-e"); + if (a != args.end()) { + istringstream is(a->second); + ret = eval(*cenv, "(command line)", is); + } + + for (list<string>::iterator f = files.begin(); f != files.end(); ++f) { + ifstream is(f->c_str()); + if (is.good()) { + ret = ret | eval(*cenv, *f, is); + } else { + std::cerr << argv[0] << ": " << *f << ": " << strerror(errno) << endl; + ++ret; + } + is.close(); + } + + if (files.empty() || args.find("-r") != args.end()) + ret = repl(*cenv); + + a = args.find("-o"); + if (a != args.end()) { + std::ofstream os(a->second.c_str()); + if (os.good()) { + cenv->write(os); + } else { + cerr << argv[0] << ": " << a->second << ": " << strerror(errno) << endl; + ++ret; + } + os.close(); + } + + delete cenv; + return ret; +} + @@ -445,7 +445,7 @@ struct CEnvPimpl; /// Compile-Time Environment struct CEnv { - CEnv(PEnv& p, CEngine& engine); + CEnv(PEnv& p, TEnv& t, CEngine& engine); ~CEnv(); typedef Env<const AST*, AST*> Code; @@ -457,6 +457,7 @@ struct CEnv { void precompile(AST* obj, CValue value) { vals.def(obj, value); } CValue compile(AST* obj); void optimise(CFunction f); + void write(std::ostream& os); CEngine& engine; PEnv& penv; @@ -470,5 +471,15 @@ private: CEnvPimpl* _pimpl; }; + +/*************************************************************************** + * EVAL/REPL/MAIN * + ***************************************************************************/ + +void initLang(PEnv& penv, TEnv& tenv); +CEnv* newCenv(PEnv& penv, TEnv& tenv); +int eval(CEnv& cenv, const string& name, istream& is); +int repl(CEnv& cenv); + #endif // TUPLR_HPP diff --git a/tuplr_llvm.cpp b/tuplr_llvm.cpp index 3c5ee17..b236bbd 100644 --- a/tuplr_llvm.cpp +++ b/tuplr_llvm.cpp @@ -15,10 +15,11 @@ * along with Tuplr. If not, see <http://www.gnu.org/licenses/>. */ -#include <fstream> +#include <map> #include <sstream> -#include "tuplr.hpp" +#include <boost/format.hpp> #include "llvm/Analysis/Verifier.h" +#include "llvm/Assembly/AsmAnnotationWriter.h" #include "llvm/DerivedTypes.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/Instructions.h" @@ -28,6 +29,7 @@ #include "llvm/Support/IRBuilder.h" #include "llvm/Target/TargetData.h" #include "llvm/Transforms/Scalar.h" +#include "tuplr.hpp" llvm::Value* LLVal(CValue v) { return static_cast<llvm::Value*>(v); } const llvm::Type* LLType(CType t) { return static_cast<const llvm::Type*>(t); } @@ -130,8 +132,8 @@ struct CEnvPimpl { Function* alloc; }; -CEnv::CEnv(PEnv& p, CEngine& eng) - : engine(eng), penv(p), tenv(p), symID(0), _pimpl(new CEnvPimpl(eng)) +CEnv::CEnv(PEnv& p, TEnv& t, CEngine& eng) + : engine(eng), penv(p), tenv(t), symID(0), _pimpl(new CEnvPimpl(eng)) { } @@ -154,6 +156,13 @@ CEnv::optimise(CFunction f) _pimpl->opt.run(*static_cast<Function*>(f)); } +void +CEnv::write(std::ostream& os) +{ + AssemblyAnnotationWriter writer; + engine.module->print(os, &writer); +} + #define LITERAL(CT, NAME, COMPILED) \ template<> CValue \ ASTLiteral<CT>::compile(CEnv& cenv) { return (COMPILED); } \ @@ -289,7 +298,7 @@ ASTCall::compile(CEnv& cenv) } assert(c); - Function* f = dynamic_cast<Function*>(LLVal(c->compile(cenv))); + Function* f = dynamic_cast<Function*>(LLVal(cenv.compile(c))); if (!f) throw Error("callee failed to compile", exp.loc); vector<Value*> params(size() - 1); @@ -601,10 +610,9 @@ repl(CEnv& cenv) return 0; } -int -main(int argc, char** argv) +void +initLang(PEnv& penv, TEnv& tenv) { - PEnv penv; penv.reg(true, "fn", PEnv::Handler(parseFn)); penv.reg(true, "if", PEnv::Handler(parseCall<ASTIf>)); penv.reg(true, "def", PEnv::Handler(parseCall<ASTDefinition>)); @@ -617,51 +625,40 @@ main(int argc, char** argv) penv.reg(false, "true", PEnv::Handler(parseLiteral<bool>, (CArg*)&trueVal)); penv.reg(false, "false", PEnv::Handler(parseLiteral<bool>, (CArg*)&falseVal)); - map<string, CArg> prims; - prims.insert(make_pair("+", CArg(Instruction::Add))); - prims.insert(make_pair("-", CArg(Instruction::Sub))); - prims.insert(make_pair("*", CArg(Instruction::Mul))); - prims.insert(make_pair("/", CArg(Instruction::FDiv))); - prims.insert(make_pair("%", CArg(Instruction::FRem))); - prims.insert(make_pair("&", CArg(Instruction::And))); - prims.insert(make_pair("|", CArg(Instruction::Or))); - prims.insert(make_pair("^", CArg(Instruction::Xor))); - prims.insert(make_pair("=", CArg(Instruction::ICmp, CmpInst::ICMP_EQ))); - prims.insert(make_pair("!=", CArg(Instruction::ICmp, CmpInst::ICMP_NE))); - prims.insert(make_pair(">", CArg(Instruction::ICmp, CmpInst::ICMP_SGT))); - prims.insert(make_pair(">=", CArg(Instruction::ICmp, CmpInst::ICMP_SGE))); - prims.insert(make_pair("<", CArg(Instruction::ICmp, CmpInst::ICMP_SLT))); - prims.insert(make_pair("<=", CArg(Instruction::ICmp, CmpInst::ICMP_SLE))); - for (map<string,CArg>::iterator p = prims.begin(); p != prims.end(); ++p) + map<string, CArg>* prims = new map<string, CArg>(); + prims->insert(make_pair("+", CArg(Instruction::Add))); + prims->insert(make_pair("-", CArg(Instruction::Sub))); + prims->insert(make_pair("*", CArg(Instruction::Mul))); + prims->insert(make_pair("/", CArg(Instruction::FDiv))); + prims->insert(make_pair("%", CArg(Instruction::FRem))); + prims->insert(make_pair("&", CArg(Instruction::And))); + prims->insert(make_pair("|", CArg(Instruction::Or))); + prims->insert(make_pair("^", CArg(Instruction::Xor))); + prims->insert(make_pair("=", CArg(Instruction::ICmp, CmpInst::ICMP_EQ))); + prims->insert(make_pair("!=", CArg(Instruction::ICmp, CmpInst::ICMP_NE))); + prims->insert(make_pair(">", CArg(Instruction::ICmp, CmpInst::ICMP_SGT))); + prims->insert(make_pair(">=", CArg(Instruction::ICmp, CmpInst::ICMP_SGE))); + prims->insert(make_pair("<", CArg(Instruction::ICmp, CmpInst::ICMP_SLT))); + prims->insert(make_pair("<=", CArg(Instruction::ICmp, CmpInst::ICMP_SLE))); + for (map<string,CArg>::iterator p = prims->begin(); p != prims->end(); ++p) penv.reg(true, p->first, PEnv::Handler(parseCall<ASTPrimitive>, &p->second)); + + tenv.def(penv.sym("Bool"), new AType(penv.sym("Bool"), Type::Int1Ty)); + tenv.def(penv.sym("Int"), new AType(penv.sym("Int"), Type::Int32Ty)); + tenv.def(penv.sym("Float"), new AType(penv.sym("Float"), Type::FloatTy)); +} - CEngine engine; - CEnv cenv(penv, engine); - - cenv.tenv.def(penv.sym("Bool"), new AType(penv.sym("Bool"), Type::Int1Ty)); - cenv.tenv.def(penv.sym("Int"), new AType(penv.sym("Int"), Type::Int32Ty)); - cenv.tenv.def(penv.sym("Float"), new AType(penv.sym("Float"), Type::FloatTy)); +CEnv* +newCenv(PEnv& penv, TEnv& tenv) +{ + CEngine* engine = new CEngine(); + CEnv* cenv = new CEnv(penv, tenv, *engine); // Host provided allocation primitive prototypes std::vector<const Type*> argsT(1, Type::Int32Ty); FunctionType* funcT = FunctionType::get(PointerType::get(Type::Int8Ty, 0), argsT, false); - cenv.alloc = Function::Create(funcT, Function::ExternalLinkage, "malloc", engine.module); - - int ret; - if (argc > 2 && !strncmp(argv[1], "-e", 3)) { - std::istringstream is(argv[2]); - ret = eval(cenv, "(command line)", is); - } else if (argc > 2 && !strncmp(argv[1], "-f", 3)) { - std::ifstream is(argv[2]); - ret = eval(cenv, argv[2], is); - is.close(); - } else { - ret = repl(cenv); - } - - //out << endl << "*** Generated Code ***" << endl; - //cenv.module->dump(); + cenv->alloc = Function::Create(funcT, Function::ExternalLinkage, "malloc", engine->module); - return ret; + return cenv; } |