diff options
author | David Robillard <d@drobilla.net> | 2009-03-06 02:57:57 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2009-03-06 02:57:57 +0000 |
commit | 2f1797c685202d88c93a73de8dfbb2c6d6da87b3 (patch) | |
tree | 597e07baacadcfe44cacb7ac05c64e9a427a35f0 /tuplr_llvm.cpp | |
parent | 7c1ea0948d9b43bfb7a86aa356eea04c1b9649ae (diff) | |
download | resp-2f1797c685202d88c93a73de8dfbb2c6d6da87b3.tar.gz resp-2f1797c685202d88c93a73de8dfbb2c6d6da87b3.tar.bz2 resp-2f1797c685202d88c93a73de8dfbb2c6d6da87b3.zip |
More generic parser function mechanism that works for atoms too.
Use atom parser methods to parse literals.
Remove the last of the language and backend specific things from core code.
git-svn-id: http://svn.drobilla.net/resp/tuplr@56 ad02d1e2-f140-0410-9f75-f8b11f17cedd
Diffstat (limited to 'tuplr_llvm.cpp')
-rw-r--r-- | tuplr_llvm.cpp | 86 |
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)); |