aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/c.cpp8
-rw-r--r--src/compile.cpp24
-rw-r--r--src/llvm.cpp33
-rw-r--r--src/resp.hpp2
4 files changed, 35 insertions, 32 deletions
diff --git a/src/c.cpp b/src/c.cpp
index afe1132..0e3596d 100644
--- a/src/c.cpp
+++ b/src/c.cpp
@@ -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;