00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef Fennel_CastInstruction_Included
00023 #define Fennel_CastInstruction_Included
00024
00025 #include "fennel/calculator/NativeInstruction.h"
00026 #include <boost/cast.hpp>
00027
00028 FENNEL_BEGIN_NAMESPACE
00029
00035 template<typename RESULT_T, typename SOURCE_T>
00036 class CastInstruction : public Instruction
00037 {
00038 public:
00039 explicit
00040 CastInstruction(
00041 RegisterRef<RESULT_T>* result,
00042 RegisterRef<SOURCE_T>* op,
00043 StandardTypeDescriptorOrdinal resultType,
00044 StandardTypeDescriptorOrdinal sourceType)
00045 : mResult(result),
00046 mOp1(op),
00047 mOp2(NULL)
00048 {}
00049
00050 virtual
00051 ~CastInstruction() {}
00052
00053 protected:
00054 RegisterRef<RESULT_T>* mResult;
00055 RegisterRef<SOURCE_T>* mOp1;
00056 RegisterRef<SOURCE_T>* mOp2;
00057 };
00058
00059 template<typename RESULT_T, typename SOURCE_T>
00060 class CastCast : public CastInstruction<RESULT_T, SOURCE_T>
00061 {
00062 public:
00063 explicit
00064 CastCast(
00065 RegisterRef<RESULT_T>* result,
00066 RegisterRef<SOURCE_T>* op1,
00067 StandardTypeDescriptorOrdinal resultType,
00068 StandardTypeDescriptorOrdinal sourceType)
00069 : CastInstruction<RESULT_T, SOURCE_T>(
00070 result, op1, resultType, sourceType)
00071 {}
00072
00073 virtual
00074 ~CastCast() {}
00075
00076 virtual void exec(TProgramCounter& pc) const {
00077
00078 pc++;
00079 if (CastInstruction<RESULT_T, SOURCE_T>::mOp1->isNull()) {
00080
00081 CastInstruction<RESULT_T, SOURCE_T>::mResult->toNull();
00082 } else {
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 SOURCE_T src = CastInstruction<RESULT_T, SOURCE_T>::mOp1->value();
00095 bool thr = false;
00096 bool resultSigned = numeric_limits<RESULT_T>::is_signed;
00097 bool sourceSigned = numeric_limits<SOURCE_T>::is_signed;
00098
00099
00100
00101 RESULT_T min = (numeric_limits<RESULT_T>::is_integer ?
00102 numeric_limits<RESULT_T>::min() :
00103 - numeric_limits<RESULT_T>::max());
00104 RESULT_T max = numeric_limits<RESULT_T>::max();
00105
00106 if (resultSigned == sourceSigned) {
00107
00108 if (max < src || min > src) {
00109 thr = true;
00110 }
00111 } else if (resultSigned && !sourceSigned) {
00112
00113 if (max < src) {
00114 thr = true;
00115 }
00116 } else {
00117
00118
00119 if (max < src || min > src) {
00120 thr = true;
00121 }
00122 }
00123 if (thr) {
00124 throw CalcMessage("22003", pc - 1);
00125 }
00126
00127
00128 try {
00129 CastInstruction<RESULT_T, SOURCE_T>::mResult->value(
00130 boost::numeric_cast<RESULT_T>(
00131 CastInstruction<RESULT_T, SOURCE_T>::mOp1->value()));
00132 } catch (boost::bad_numeric_cast) {
00133
00134
00135
00136 throw CalcMessage("22003", pc - 1);
00137 }
00138 }
00139 }
00140
00141 static const char* longName()
00142 {
00143 return "NativeCast";
00144 }
00145
00146 static const char* shortName()
00147 {
00148 return "CAST";
00149 }
00150
00151 static int numArgs()
00152 {
00153 return 2;
00154 }
00155
00156 void describe(string& out, bool values) const {
00157 RegisterRef<char> dummy;
00158 describeHelper(
00159 out, values, longName(), shortName(),
00160 CastInstruction<RESULT_T, SOURCE_T>::mResult,
00161 CastInstruction<RESULT_T, SOURCE_T>::mOp1,
00162 CastInstruction<RESULT_T, SOURCE_T>::mOp2);
00163 }
00164
00165 static InstructionSignature
00166 signature(
00167 StandardTypeDescriptorOrdinal type1,
00168 StandardTypeDescriptorOrdinal type2)
00169 {
00170 vector<StandardTypeDescriptorOrdinal> v;
00171 v.push_back(type1);
00172 v.push_back(type2);
00173 return InstructionSignature(shortName(), v);
00174 }
00175
00176 static Instruction*
00177 create(InstructionSignature const & sig)
00178 {
00179 assert(sig.size() == numArgs());
00180 return new CastCast(
00181 static_cast<RegisterRef<RESULT_T>*> (sig[0]),
00182 static_cast<RegisterRef<SOURCE_T>*> (sig[1]),
00183 (sig[0])->type(),
00184 (sig[1])->type());
00185 }
00186 };
00187
00188 #define TTT(a)
00189
00190 class FENNEL_CALCULATOR_EXPORT CastInstructionRegister
00191 : InstructionRegister {
00192
00193
00194 template < template <typename, typename > class INSTCLASS2 >
00195 static void
00196 registerTypes(
00197 vector<StandardTypeDescriptorOrdinal> const & t1,
00198 vector<StandardTypeDescriptorOrdinal> const & t2)
00199 {
00200 for (uint i = 0; i < t1.size(); i++) {
00201 for (uint j = 0; j < t2.size(); j++) {
00202 StandardTypeDescriptorOrdinal type1 = t1[i];
00203 StandardTypeDescriptorOrdinal type2 = t2[j];
00204
00205 InstructionSignature sig =
00206 INSTCLASS2<char, char>::signature(type1, type2);
00207 #include "fennel/calculator/InstructionRegisterSwitchCast.h"
00208
00209
00210 }
00211 }
00212 }
00213
00214 public:
00215 static void
00216 registerInstructions() {
00217 vector<StandardTypeDescriptorOrdinal> t;
00218 t = InstructionSignature::typeVector
00219 (StandardTypeDescriptor::isNativeNotBool);
00220
00221
00222
00223
00224
00225
00226 registerTypes<fennel::CastCast>(t, t);
00227 }
00228 };
00229
00230
00231 FENNEL_END_NAMESPACE
00232
00233 #endif
00234
00235
00236