diff options
-rw-r--r-- | src/c.cpp | 8 | ||||
-rw-r--r-- | src/compile.cpp | 24 | ||||
-rw-r--r-- | src/llvm.cpp | 33 | ||||
-rw-r--r-- | src/resp.hpp | 2 |
4 files changed, 35 insertions, 32 deletions
@@ -160,7 +160,7 @@ struct CEngine : public Engine { CVal compileString(CEnv& cenv, const char* str); CVal compilePrimitive(CEnv& cenv, const ATuple* prim); CVal compileIf(CEnv& cenv, const ATuple* aif); - CVal compileMatch(CEnv& cenv, const ATuple* match); + CVal compileIsA(CEnv& cenv, CVal rtti, const ASymbol* tag) { return NULL; } CVal compileGlobal(CEnv& cenv, const AType* type, const string& sym, CVal val); CVal compileGlobalGet(CEnv& cenv, const string& sym, CVal val); @@ -266,12 +266,6 @@ CEngine::compileIf(CEnv& cenv, const ATuple* aif) } CVal -CEngine::compileMatch(CEnv& cenv, const ATuple* match) -{ - return NULL; -} - -CVal CEngine::compilePrimitive(CEnv& cenv, const ATuple* prim) { ATuple::const_iterator i = prim->begin(); diff --git a/src/compile.cpp b/src/compile.cpp index 554fab6..48c2b0a 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -151,6 +151,28 @@ compile_if(CEnv& cenv, const ATuple* aif) throw() return cenv.engine()->compileIfEnd(cenv, state, elseV, cenv.type(aif)); } +static CVal +compile_match(CEnv& cenv, const ATuple* match) throw() +{ + IfState state = cenv.engine()->compileIfStart(cenv); + CVal matchee = resp_compile(cenv, match->list_ref(1)); + CVal rtti = cenv.engine()->compileDot(cenv, matchee, 0); + + size_t idx = 1; + for (ATuple::const_iterator i = match->iter_at(2); i != match->end(); ++idx) { + const AST* pat = *i++; + const AST* body = *i++; + const ASymbol* sym = pat->as_tuple()->head()->as_symbol(); + + CVal condV = cenv.engine()->compileIsA(cenv, rtti, sym); + + cenv.engine()->compileIfBranch(cenv, state, condV, body); + } + + const AType* type = cenv.type(match); + return cenv.engine()->compileIfEnd(cenv, state, NULL, type); +} + CVal resp_compile(CEnv& cenv, const AST* ast) throw() { @@ -185,7 +207,7 @@ resp_compile(CEnv& cenv, const AST* ast) throw() else if (form == ".") return compile_dot(cenv, call); else if (form == "match") - return cenv.engine()->compileMatch(cenv, call); + return compile_match(cenv, call); else if (form == "def-type") return NULL; else diff --git a/src/llvm.cpp b/src/llvm.cpp index 6975861..eeb584c 100644 --- a/src/llvm.cpp +++ b/src/llvm.cpp @@ -206,7 +206,7 @@ struct LLVMEngine : public Engine { CVal compileString(CEnv& cenv, const char* str); CVal compilePrimitive(CEnv& cenv, const ATuple* prim); CVal compileIf(CEnv& cenv, const ATuple* aif); - CVal compileMatch(CEnv& cenv, const ATuple* match); + CVal compileIsA(CEnv& cenv, CVal rtti, const ASymbol* tag); CVal compileGlobal(CEnv& cenv, const AType* type, const string& sym, CVal val); CVal compileGlobalGet(CEnv& cenv, const string& sym, CVal val); @@ -405,7 +405,10 @@ LLVMEngine::compileIfEnd(CEnv& cenv, IfState s, CVal elseV, const AType* type) { LLVMIfState* state = (LLVMIfState*)s; LLVMEngine* engine = reinterpret_cast<LLVMEngine*>(cenv.engine()); - + + if (!elseV) + elseV = Constant::getNullValue(llType(type)); + // Emit end of final else block engine->builder.CreateBr(state->mergeBB); state->branches.push_back(make_pair(llVal(elseV), engine->builder.GetInsertBlock())); @@ -420,29 +423,13 @@ LLVMEngine::compileIfEnd(CEnv& cenv, IfState s, CVal elseV, const AType* type) } CVal -LLVMEngine::compileMatch(CEnv& cenv, const ATuple* match) +LLVMEngine::compileIsA(CEnv& cenv, CVal rtti, const ASymbol* tag) { - LLVMEngine* engine = reinterpret_cast<LLVMEngine*>(cenv.engine()); - IfState state = compileIfStart(cenv); - CVal matchee = resp_compile(cenv, match->list_ref(1)); - Value* rtti = llVal(compileDot(cenv, matchee, 0)); - - size_t idx = 1; - for (ATuple::const_iterator i = match->iter_at(2); i != match->end(); ++idx) { - const AST* pat = *i++; - const AST* body = *i++; - const ASymbol* sym = pat->as_tuple()->head()->as_symbol(); - const AType* patT = new AType(sym, 0, Cursor()); - - Value* typeV = llVal(resp_compile(cenv, patT)); - Value* condV = engine->builder.CreateICmp(CmpInst::ICMP_EQ, rtti, typeV); - - compileIfBranch(cenv, state, condV, body); - } + LLVMEngine* engine = reinterpret_cast<LLVMEngine*>(cenv.engine()); + const AType* patT = new AType(tag, 0, Cursor()); + Value* typeV = llVal(resp_compile(cenv, patT)); - const AType* type = cenv.type(match); - CVal elseV = Constant::getNullValue(llType(type)); - return compileIfEnd(cenv, state, elseV, type); + return engine->builder.CreateICmp(CmpInst::ICMP_EQ, llVal(rtti), typeV); } CVal diff --git a/src/resp.hpp b/src/resp.hpp index 7dc9f16..a3117a0 100644 --- a/src/resp.hpp +++ b/src/resp.hpp @@ -721,7 +721,7 @@ struct Engine { virtual CVal compileString(CEnv& cenv, const char* str) = 0; virtual CVal compileCall(CEnv& cenv, CFunc f, const AType* fT, ValVec& args) = 0; virtual CVal compilePrimitive(CEnv& cenv, const ATuple* prim) = 0; - virtual CVal compileMatch(CEnv& cenv, const ATuple* match) = 0; + virtual CVal compileIsA(CEnv& cenv, CVal rtti, const ASymbol* tag) = 0; virtual CVal compileGlobal(CEnv& cenv, const AType* t, const string& sym, CVal val) = 0; virtual CVal compileGlobalGet(CEnv& cenv, const string& sym, CVal val) = 0; |