00001
#ifndef EXPRUTIL_H
00002
#define EXPRUTIL_H
00003
00004
#include "NArgs.h"
00005
00006
00007
00008
using namespace Borealis;
00009
00010 inline vector<ptr<Expression> >
makeArgs(ptr<Expression> a = ptr<Expression>(),
00011 ptr<Expression> b = ptr<Expression>(),
00012 ptr<Expression> c = ptr<Expression>())
00013 {
00014 vector<ptr<Expression> > out;
00015
00016
if (a) { out.push_back(a); }
00017
if (b) { out.push_back(b); }
00018
if (c) { out.push_back(c); }
00019
00020
return out;
00021 }
00022
00023
00024
00025
00026
00027
template<
typename T>
00028 class ConstantExpression :
public TypedExpression<T> {
00029
public:
00030 ConstantExpression(T val) : _val(val) {}
00031 T
evalImpl(EvalAs<T>,
const EvalContext& ctxt)
throw (EvalException) {
return _val; }
00032
00033 T
getValue()
const {
return _val; }
00034 string
value()
const {
return to_string(_val); }
00035
00036
private:
00037 T _val;
00038 };
00039
00040
template<>
00041 class ConstantExpression<EString> :
public TypedExpression<EString> {
00042
public:
00043 ConstantExpression(string val) : _val(val) {}
00044 EString
evalImpl(EvalAs<EString>,
const EvalContext& ctxt)
throw (EvalException) {
return EString(_val); }
00045
00046 string
value()
const {
return "\"" + to_escaped_string(
to_string(_val)) +
"\""; }
00047
00048
private:
00049 string _val;
00050 };
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
template<
typename T>
00062 class FieldExpression :
public TypedExpression<T> {
00063
public:
00064 FieldExpression(
unsigned int which_tuple,
unsigned int offset) :
00065 _which_tuple(which_tuple), _offset(offset) {}
00066
00067 T
evalImpl(EvalAs<T>,
const EvalContext& ctxt)
throw (EvalException) {
00068
return *(T*)(ctxt.getTuple(_which_tuple) + _offset);
00069 }
00070
00071
private:
00072
unsigned int _which_tuple;
00073
unsigned int _offset;
00074 };
00075
00076
template<>
00077 class FieldExpression<EString> :
public TypedExpression<EString> {
00078
public:
00079 FieldExpression(
unsigned int which_tuple,
unsigned int offset,
unsigned int length) :
00080 _which_tuple(which_tuple), _offset(offset), _length(length) {}
00081
00082 EString
evalImpl(EvalAs<EString>,
const EvalContext& ctxt)
throw (EvalException) {
00083
const char *field = ctxt.getTuple(_which_tuple) + _offset;
00084
const char *end = field + _length;
00085
00086
00087
while (end != field) {
00088
if (*(end - 1) != 0)
break;
00089 --end;
00090 }
00091
00092
return EString(field, end - field);
00093 }
00094
00095 int32 getStringLength()
const {
return _length; }
00096
00097
private:
00098
unsigned int _which_tuple;
00099
unsigned int _offset, _length;
00100 };
00101
00102
00103
00104
00105
00106
00107
00108 #define OP(N, Name, Out, Expr) \
00109
template<typename T> \
00110
class Name##Expression : public TypedExpression<Out>, NArgs { \
00111
public: \
00112
Name##Expression(const NArgs& args) throw (ExprException) : NArgs(args) { \
00113
requireNumArgs(N); \
00114
} \
00115
Out evalImpl(EvalAs<Out>, const EvalContext& ctxt) throw (EvalException) { \
00116
return Expr; \
00117
} \
00118
}; \
00119
struct Name##Expressions { \
00120
template <class T> struct forType { \
00121
typedef Name##Expression<T> ExprType; \
00122
}; \
00123
};
00124
00125
00126
template <
class T>
00127 inline T
exprMod(T a, T b) {
return a % b; }
00128
00129
template <>
00130 inline single
exprMod( single a, single b) {
return( fmodf( a, b )); }
00131
00132
template <>
00133 inline double exprMod(
double a,
double b) {
return( fmod( a, b )); }
00134
00135
00136
template <
class T>
00137 inline T
divide(T a, T b) {
00138
if (b == 0) {
00139 WARN <<
"Divided by zero.";
00140
return numeric_limits<T>::infinity();
00141 }
else {
00142
return a / b;
00143 }
00144 }
00145
00146
00147
00148 #define A (_args[0]->template eval<T>(ctxt))
00149 #define B (_args[1]->template eval<T>(ctxt))
00150 #define C (_args[2]->template eval<T>(ctxt))
00151
00152 #define A_as(type) (_args[0]->template eval<type>(ctxt))
00153
00154
OP(2, Plus, T, A + B);
00155
OP(2, Minus, T, A - B);
00156
OP(2, Times, T, A * B);
00157
OP(2, Div, T,
divide(A,B));
00158
OP(2, Mod, T,
exprMod(A, B));
00159
OP(2, Concat, T,
A.concat(B, ctxt.getPool()));
00160
00161
OP(2, EQ,
bool, A == B);
00162
OP(2, NE,
bool, A != B);
00163
OP(2, LT,
bool, A < B);
00164
OP(2, GT,
bool, A > B);
00165
OP(2, LE,
bool, A <= B);
00166
OP(2, GE,
bool, A >= B);
00167
00168
OP(2, And,
bool, A && B);
00169
OP(2, Or,
bool, A || B);
00170
00171
OP(1, UMinus, T, -A);
00172
OP(1, Not, T, !A);
00173
00174
OP(3, IfThenElse, T,
A_as(
bool) ? B : C);
00175
00176
#undef A
00177
#undef B
00178
#undef C
00179
00180
00181
00182
template <
typename Types>
00183 ptr<Expression>
arithPromote( ptr<Expression> l, ptr<Expression> r )
00184
throw( ExprException )
00185 {
00186
if ( l->is_numeric() && r->is_numeric() )
00187 {
if (( l->getType() == DataType::DOUBLE ) ||
00188 ( r->getType() == DataType::DOUBLE ))
00189 {
00190
return( ptr<Expression>(
00191
new typename Types::forType<double>::ExprType(
00192
NArgs( l, r ))));
00193 }
00194
else if (( l->getType() == DataType::SINGLE ) ||
00195 ( r->getType() == DataType::SINGLE ) ||
00196 ( r->getType() == DataType::FLOAT ) ||
00197 ( r->getType() == DataType::FLOAT ))
00198 {
00199
return( ptr<Expression>(
00200
new typename Types::forType<single>::ExprType(
00201
NArgs( l, r ))));
00202 }
00203
else if (( l->getType() == DataType::LONG ) ||
00204 ( r->getType() == DataType::LONG ))
00205 {
00206
return( ptr<Expression>(
00207
new typename Types::forType<int64>::ExprType(
00208
NArgs( l, r ))));
00209 }
00210
else
00211 {
return( ptr<Expression>(
00212
new typename Types::forType<int32>::ExprType(
00213
NArgs( l, r ))));
00214 }
00215 }
00216
00217
Throw( ExprException,
"invalid types" );
00218 }
00219
00220
template <
typename Types>
00221 ptr<Expression>
relPromote( ptr<Expression> l, ptr<Expression> r )
00222
throw( ExprException )
00223 {
00224
if (( l->getType() == DataType::BOOL ) &&
00225 ( r->getType() == DataType::BOOL ))
00226 {
00227
return( ptr<Expression>(
00228
new typename Types::forType<bool>::ExprType(
00229
NArgs( l, r ))));
00230 }
00231
else if ( l->is_numeric() && r->is_numeric())
00232 {
00233
if (( l->getType() == DataType::DOUBLE ) ||
00234 ( r->getType() == DataType::DOUBLE ))
00235 {
00236
return( ptr<Expression>(
00237
new typename Types::forType<double>::ExprType(
00238
NArgs( l, r ))));
00239 }
00240
else if (( l->getType() == DataType::SINGLE ) ||
00241 ( r->getType() == DataType::SINGLE ) ||
00242 ( r->getType() == DataType::FLOAT ) ||
00243 ( r->getType() == DataType::FLOAT ))
00244 {
00245
return( ptr<Expression>(
00246
new typename Types::forType<single>::ExprType(
00247
NArgs( l, r ))));
00248 }
00249
else if (( l->getType() == DataType::LONG ) ||
00250 ( r->getType() == DataType::LONG ))
00251 {
00252
return( ptr<Expression>(
00253
new typename Types::forType<int64>::ExprType(
00254
NArgs( l, r ))));
00255 }
00256
else
00257 {
return( ptr<Expression>(
00258
new typename Types::forType<int32>::ExprType(
00259
NArgs( l, r ))));
00260 }
00261 }
00262
else if (( l->getType() == DataType::STRING ) &&
00263 ( r->getType() == DataType::STRING ))
00264 {
00265
return( ptr<Expression>(
00266
new typename Types::forType<EString>::ExprType(
00267
NArgs( l, r ))));
00268 }
00269
else
00270 {
Throw(ExprException,
"invalid types");
00271 }
00272 }
00273
00274
00275
#endif // EXPRUTIL_H