From 2f1797c685202d88c93a73de8dfbb2c6d6da87b3 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Fri, 6 Mar 2009 02:57:57 +0000 Subject: 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 --- tuplr_llvm.cpp | 86 ++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 50 insertions(+), 36 deletions(-) (limited to 'tuplr_llvm.cpp') 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, CArg(Instruction:: O, A)) PEnv penv; - penv.reg("fn", PEnv::Parser(parseFn)); - penv.reg("if", PEnv::Parser(parseAST)); - penv.reg("def", PEnv::Parser(parseAST)); - penv.reg("cons", PEnv::Parser(parseAST)); - penv.reg("car", PEnv::Parser(parseAST)); - penv.reg("cdr", PEnv::Parser(parseAST)); - 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)); + penv.reg(true, "def", PEnv::Handler(parseCall)); + penv.reg(true, "cons", PEnv::Handler(parseCall)); + penv.reg(true, "car", PEnv::Handler(parseCall)); + penv.reg(true, "cdr", PEnv::Handler(parseCall)); + + bool trueVal = true; + bool falseVal = false; + penv.reg(false, "true", PEnv::Handler(parseLiteral, (CArg*)&trueVal)); + penv.reg(false, "false", PEnv::Handler(parseLiteral, (CArg*)&falseVal)); + + map 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::iterator p = prims.begin(); p != prims.end(); ++p) + penv.reg(true, p->first, PEnv::Handler(parseCall, &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)); -- cgit v1.2.1