aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ack.tpr2
-rw-r--r--tuplr.cpp87
-rw-r--r--tuplr.hpp13
-rw-r--r--tuplr_llvm.cpp91
4 files changed, 144 insertions, 49 deletions
diff --git a/ack.tpr b/ack.tpr
index 567a360..1fe38d5 100644
--- a/ack.tpr
+++ b/ack.tpr
@@ -4,5 +4,5 @@
(= 0 n) (ack (- m 1) 1)
(ack (- m 1) (ack m (- n 1))))))
-(ack 3 12)
+(ack 3 10)
diff --git a/tuplr.cpp b/tuplr.cpp
index 6df6fec..121bd6d 100644
--- a/tuplr.cpp
+++ b/tuplr.cpp
@@ -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;
+}
+
diff --git a/tuplr.hpp b/tuplr.hpp
index ba4f9a9..bd4788c 100644
--- a/tuplr.hpp
+++ b/tuplr.hpp
@@ -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;
}