aboutsummaryrefslogtreecommitdiffstats
path: root/tuplr_llvm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tuplr_llvm.cpp')
-rw-r--r--tuplr_llvm.cpp86
1 files changed, 50 insertions, 36 deletions
diff --git a/tuplr_llvm.cpp b/tuplr_llvm.cpp
index 8d1f1db..3c5ee17 100644
--- a/tuplr_llvm.cpp
+++ b/tuplr_llvm.cpp
@@ -40,6 +40,12 @@ struct CEngine {
llvm::IRBuilder<> builder;
};
+struct CArg {
+ CArg(int o=0, int a=0) : op(o), arg(a) {}
+ int op;
+ int arg;
+};
+
using namespace llvm;
using namespace std;
using boost::format;
@@ -76,13 +82,13 @@ ASTPrimitive::constrain(TEnv& tenv) const
{
FOREACH(const_iterator, p, *this)
(*p)->constrain(tenv);
- if (OP_IS_A(arg.op, Instruction::BinaryOps)) {
+ if (OP_IS_A(arg->op, Instruction::BinaryOps)) {
if (size() <= 2) throw Error((format("`%1%' requires at least 2 arguments")
% at(0)->str()).str(), exp.loc);
AType* tvar = tenv.type(this);
for (size_t i = 1; i < size(); ++i)
tenv.constrain(at(i), tvar);
- } else if (arg.op == Instruction::ICmp) {
+ } else if (arg->op == Instruction::ICmp) {
if (size() != 3) throw Error((format("`%1%' requires exactly 2 arguments")
% at(0)->str()).str(), exp.loc);
tenv.constrain(at(1), tenv.type(at(2)));
@@ -362,30 +368,30 @@ ASTPrimitive::compile(CEnv& cenv)
Value* a = LLVal(cenv.compile(at(1)));
Value* b = LLVal(cenv.compile(at(2)));
- if (OP_IS_A(arg.op, Instruction::BinaryOps)) {
- const Instruction::BinaryOps bo = (Instruction::BinaryOps)arg.op;
+ if (OP_IS_A(arg->op, Instruction::BinaryOps)) {
+ const Instruction::BinaryOps bo = (Instruction::BinaryOps)arg->op;
if (size() == 2)
return cenv.compile(at(1));
Value* val = cenv.engine.builder.CreateBinOp(bo, a, b);
for (size_t i = 3; i < size(); ++i)
val = cenv.engine.builder.CreateBinOp(bo, val, LLVal(cenv.compile(at(i))));
return val;
- } else if (arg.op == Instruction::ICmp) {
+ } else if (arg->op == Instruction::ICmp) {
bool isInt = cenv.tenv.type(at(1))->str() == "Int";
if (isInt) {
- return cenv.engine.builder.CreateICmp((CmpInst::Predicate)arg.arg, a, b);
+ return cenv.engine.builder.CreateICmp((CmpInst::Predicate)arg->arg, a, b);
} else {
// Translate to floating point operation
- switch (arg.arg) {
- case CmpInst::ICMP_EQ: arg.arg = CmpInst::FCMP_OEQ; break;
- case CmpInst::ICMP_NE: arg.arg = CmpInst::FCMP_ONE; break;
- case CmpInst::ICMP_SGT: arg.arg = CmpInst::FCMP_OGT; break;
- case CmpInst::ICMP_SGE: arg.arg = CmpInst::FCMP_OGE; break;
- case CmpInst::ICMP_SLT: arg.arg = CmpInst::FCMP_OLT; break;
- case CmpInst::ICMP_SLE: arg.arg = CmpInst::FCMP_OLE; break;
+ switch (arg->arg) {
+ case CmpInst::ICMP_EQ: arg->arg = CmpInst::FCMP_OEQ; break;
+ case CmpInst::ICMP_NE: arg->arg = CmpInst::FCMP_ONE; break;
+ case CmpInst::ICMP_SGT: arg->arg = CmpInst::FCMP_OGT; break;
+ case CmpInst::ICMP_SGE: arg->arg = CmpInst::FCMP_OGE; break;
+ case CmpInst::ICMP_SLT: arg->arg = CmpInst::FCMP_OLT; break;
+ case CmpInst::ICMP_SLE: arg->arg = CmpInst::FCMP_OLE; break;
default: throw Error("Unknown primitive", exp.loc);
}
- return cenv.engine.builder.CreateFCmp((CmpInst::Predicate)arg.arg, a, b);
+ return cenv.engine.builder.CreateFCmp((CmpInst::Predicate)arg->arg, a, b);
}
}
throw Error("Unknown primitive", exp.loc);
@@ -598,31 +604,39 @@ repl(CEnv& cenv)
int
main(int argc, char** argv)
{
-#define PRIM(O, A) PEnv::Parser(parseAST<ASTPrimitive>, CArg(Instruction:: O, A))
PEnv penv;
- penv.reg("fn", PEnv::Parser(parseFn));
- penv.reg("if", PEnv::Parser(parseAST<ASTIf>));
- penv.reg("def", PEnv::Parser(parseAST<ASTDefinition>));
- penv.reg("cons", PEnv::Parser(parseAST<ASTConsCall>));
- penv.reg("car", PEnv::Parser(parseAST<ASTCarCall>));
- penv.reg("cdr", PEnv::Parser(parseAST<ASTCdrCall>));
- penv.reg("+", PRIM(Add, 0));
- penv.reg("-", PRIM(Sub, 0));
- penv.reg("*", PRIM(Mul, 0));
- penv.reg("/", PRIM(FDiv, 0));
- penv.reg("%", PRIM(FRem, 0));
- penv.reg("&", PRIM(And, 0));
- penv.reg("|", PRIM(Or, 0));
- penv.reg("^", PRIM(Xor, 0));
- penv.reg("=", PRIM(ICmp, CmpInst::ICMP_EQ));
- penv.reg("!=", PRIM(ICmp, CmpInst::ICMP_NE));
- penv.reg(">", PRIM(ICmp, CmpInst::ICMP_SGT));
- penv.reg(">=", PRIM(ICmp, CmpInst::ICMP_SGE));
- penv.reg("<", PRIM(ICmp, CmpInst::ICMP_SLT));
- penv.reg("<=", PRIM(ICmp, CmpInst::ICMP_SLE));
+ penv.reg(true, "fn", PEnv::Handler(parseFn));
+ penv.reg(true, "if", PEnv::Handler(parseCall<ASTIf>));
+ penv.reg(true, "def", PEnv::Handler(parseCall<ASTDefinition>));
+ penv.reg(true, "cons", PEnv::Handler(parseCall<ASTConsCall>));
+ penv.reg(true, "car", PEnv::Handler(parseCall<ASTCarCall>));
+ penv.reg(true, "cdr", PEnv::Handler(parseCall<ASTCdrCall>));
+
+ bool trueVal = true;
+ bool falseVal = false;
+ 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)
+ penv.reg(true, p->first, PEnv::Handler(parseCall<ASTPrimitive>, &p->second));
CEngine engine;
- CEnv cenv(penv, 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));