00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00027 #include <sstream>
00028 #include "ShEval.hpp"
00029 #include "ShVariant.hpp"
00030 #include "ShCastManager.hpp"
00031
00032 namespace SH {
00033
00034 ShEval* ShEval::m_instance = 0;
00035
00036
00037 #define SH_EVALOP_CACHE
00038
00039 void ShEval::operator()(ShOperation op, ShVariant* dest,
00040 const ShVariant* a, const ShVariant* b, const ShVariant* c) const
00041 {
00042 #ifdef SH_DEBUG_SHEVAL
00043 SH_DEBUG_PRINT("PRE OP=" << opInfo[op].name << " "
00044 << (dest ? dest->encodeArray() : "NULL") << " = "
00045 << (a ? a->encodeArray() : "NULL") << ", "
00046 << (b ? b->encodeArray() : "NULL") << ", "
00047 << (c ? c->encodeArray() : "NULL"));
00048 #endif
00049
00050 const ShEvalOpInfo *evalOpInfo =
00051 getEvalOpInfo(op, dest ? dest->valueType() : SH_VALUETYPE_END,
00052 a ? a->valueType() : SH_VALUETYPE_END,
00053 b ? b->valueType() : SH_VALUETYPE_END,
00054 c ? c->valueType() : SH_VALUETYPE_END);
00055 if(!evalOpInfo) {
00056 #ifdef SH_DEBUG_SHEVAL
00057 SH_DEBUG_PRINT("Unable to find eval op!");
00058 SH_DEBUG_ASSERT(0);
00059 return;
00060 #endif
00061 }
00062
00063 const ShEvalOp* evalOp = evalOpInfo->m_evalOp;
00064
00065
00066
00067 ShCastManager *castmgr = ShCastManager::instance();
00068
00069
00070 ShVariant *cdest;
00071 const ShVariant *ca, *cb, *cc;
00072 bool newd, newa, newb, newc;
00073 newd = castmgr->doAllocCast(cdest, dest, evalOpInfo->m_dest, SH_HOST);
00074 newa = castmgr->doAllocCast(ca, a, evalOpInfo->m_src[0], SH_HOST);
00075 newb = castmgr->doAllocCast(cb, b, evalOpInfo->m_src[1], SH_HOST);
00076 newc = castmgr->doAllocCast(cc, c, evalOpInfo->m_src[2], SH_HOST);
00077
00078 (*evalOp)(cdest, ca, cb, cc);
00079
00080
00081
00082 if(newd) {
00083 castmgr->doCast(dest, cdest);
00084 delete cdest;
00085 }
00086 if(newa) delete const_cast<ShVariant*>(ca);
00087 if(newb) delete const_cast<ShVariant*>(cb);
00088 if(newc) delete const_cast<ShVariant*>(cc);
00089
00090 #ifdef SH_DEBUG_SHEVAL
00091 SH_DEBUG_PRINT(" RES=" << opInfo[op].name << " "
00092 << (dest ? dest->encodeArray() : "NULL") << " = "
00093 << (a ? a->encodeArray() : "NULL") << ", "
00094 << (b ? b->encodeArray() : "NULL") << ", "
00095 << (c ? c->encodeArray() : "NULL"));
00096 #endif
00097 }
00098
00099 void ShEval::addOp(ShOperation op, const ShEvalOp* evalOp, ShValueType dest,
00100 ShValueType src0, ShValueType src1, ShValueType src2)
00101 {
00102 m_evalOpMap[op].push_back(ShEvalOpInfo(op, evalOp, dest, src0, src1, src2));
00103 m_evalOpCache(op, src0, src1, src2) = &(m_evalOpMap[op].back());
00104 }
00105
00106 const ShEvalOpInfo* ShEval::getEvalOpInfo(ShOperation op, ShValueType dest,
00107 ShValueType src0, ShValueType src1, ShValueType src2) const
00108 {
00109 #ifdef SH_DEBUG_SHEVAL
00110 SH_DEBUG_PRINT("ShEval mapping op=" << opInfo[op].name << " dest,src[0-2]= "
00111 << shValueTypeName(dest)
00112 << ", " << shValueTypeName(src0)
00113 << ", " << shValueTypeName(src1)
00114 << ", " << shValueTypeName(src2));
00115 #endif
00116
00117 #ifdef SH_EVALOP_CACHE
00118 const ShEvalOpInfo*& result = m_evalOpCache(op, src0, src1, src2);
00119 if(result) {
00120 #ifdef SH_DEBUG_SHEVAL
00121 SH_DEBUG_PRINT(" cached result=" << result->encode());
00122 #endif
00123 return result;
00124 }
00125 #else
00126 const ShEvalOpinfo* result = 0;
00127 #endif
00128
00129
00130
00131
00132
00133 const OpInfoList &oiList = m_evalOpMap[op];
00134 OpInfoList::const_iterator I;
00135 int mindist = 2000000001;
00136
00137 ShCastManager* castmgr = ShCastManager::instance();
00138 for(I = oiList.begin(); I != oiList.end(); ++I) {
00139
00140 int dist = 0;
00141 int arity = opInfo[op].arity;
00142 if(arity > 0) dist += castmgr->castDist(I->m_src[0], src0);
00143 if(arity > 1) dist += castmgr->castDist(I->m_src[1], src1);
00144 if(arity > 2) dist += castmgr->castDist(I->m_src[2], src2);
00145
00146 #ifdef SH_DEBUG_SHEVAL
00147 SH_DEBUG_PRINT(" dist=" << mindist << " to " << I->encode());
00148 #endif
00149
00150 if(dist < mindist) {
00151 mindist = dist;
00152 result = &*I;
00153 }
00154 }
00155
00156 #ifdef SH_DEBUG_SHEVAL
00157 if(result) {
00158 SH_DEBUG_PRINT(" result=" << result->encode());
00159 }
00160 #endif
00161
00162 return result;
00163 }
00164
00165 ShStatementInfo* ShEvalOpInfo::clone() const
00166 {
00167 return new ShEvalOpInfo(m_op, m_evalOp, m_dest, m_src[0], m_src[1], m_src[2]);
00168 }
00169
00170 std::string ShEvalOpInfo::encode() const
00171 {
00172 std::ostringstream out;
00173 out << opInfo[m_op].name << ",";
00174 out << (m_dest != SH_VALUETYPE_END ? shTypeInfo(m_dest)->name() : "NULL");
00175 for(int i = 0; i < 3; ++i) out << ", " << (m_src[i] != SH_VALUETYPE_END ? shTypeInfo(m_src[i])->name() : "NULL");
00176 return out.str();
00177 }
00178
00179 std::string ShEval::availableOps() const
00180 {
00181 std::ostringstream out;
00182 for(int i = 0; i < (int)SH_OPERATION_END; ++i) {
00183 for(OpInfoList::const_iterator I = m_evalOpMap[i].begin();
00184 I != m_evalOpMap[i].end(); ++I) {
00185 out << I->encode() << std::endl;
00186 }
00187 }
00188 return out.str();
00189 }
00190
00191 ShEval* ShEval::instance()
00192 {
00193 if(!m_instance) m_instance = new ShEval();
00194 return m_instance;
00195
00196 }
00197
00198 ShEval::ShEval()
00199 {
00200 }
00201
00202 ShEvalOpInfo::ShEvalOpInfo(ShOperation op, const ShEvalOp* evalOp,
00203 ShValueType dest, ShValueType src0, ShValueType src1, ShValueType src2)
00204 : m_op(op), m_evalOp(evalOp), m_dest(dest)
00205 {
00206 m_src[0] = src0;
00207 m_src[1] = src1;
00208 m_src[2] = src2;
00209 }
00210
00211 ShEvalOp::~ShEvalOp()
00212 {}
00213
00214
00215 }