Browse Source

Use templates for generating standart arifmetic functions.

Automatic translation of strings to numbers in arifmetic functions.
ObjPtr
Michael Uleysky 9 years ago
parent
commit
c218ef8eaf
  1. 97
      include/builtin.h
  2. 123
      src/builtin.cpp
  3. 14
      src/init.cpp

97
include/builtin.h

@ -1,9 +1,92 @@
#include <cmath>
#include "object.h" #include "object.h"
ObjectBase* Arifm_Add(const ObjectList* input); template<class O>
ObjectBase* Arifm_Sub(const ObjectList* input); struct Valued
ObjectBase* Arifm_Mul(const ObjectList* input); {
ObjectBase* Arifm_Div(const ObjectList* input); double operator ()(const O* q, bool* isok) {return q->Value();}
ObjectBase* Arifm_Pow(const ObjectList* input); };
ObjectBase* Arifm_Neg(const ObjectList* input);
ObjectBase* Arifm_Pos(const ObjectList* input); template<>
struct Valued<ObjectString>
{
double operator ()(const ObjectString* q, bool* isok) {double d=0; *isok=str2double(q->Value(),&d); return d;}
};
template<class O>
struct Valuei
{
int64_t operator ()(const O* q, bool* isok) {return q->Value();}
};
template<>
struct Valuei<ObjectString>
{
int64_t operator ()(const ObjectString* q, bool* isok) {int64_t i=0; *isok=str2int(q->Value(),&i); return i;}
};
template<class T> class OpAdd {public: static T V(T a1, T a2) {return a1+a2;}};
template<class T> class OpSub {public: static T V(T a1, T a2) {return a1-a2;}};
template<class T> class OpMul {public: static T V(T a1, T a2) {return a1*a2;}};
template<class T> class OpDiv {public: static T V(T a1, T a2) {return a1/a2;}};
template<class T> class OpPow {public: static T V(T a1, T a2) {return pow(a1,a2);}};
template<class T> class OpNeg {public: static T V(T a) {return -a;}};
template<class T> class OpPos {public: static T V(T a) {return +a;}};
template<template<typename> class Op, bool intArifm=true>
ObjectBase* Arifm2(const ObjectList* input)
{
if(input->Size()!=2) return 0;
const ObjectBase *arg1=input->At(0),*arg2=input->At(1);
OBTypeM<Valuei,ObjectInt,ObjectString> i1(arg1), i2(arg2);
OBTypeM<Valued,ObjectReal,ObjectInt,ObjectString> r1(arg1), r2(arg2);
bool isok;
// Integer arifmetic
isok=true;
if(i1 && i2 && intArifm)
{
int64_t v1=i1(&isok),v2=i2(&isok);
if(isok) return new ObjectInt(Op<int64_t>::V(v1,v2));
}
// Real arifmetic
isok=true;
if(r1 && r2)
{
double v1=r1(&isok),v2=r2(&isok);
if(isok) return new ObjectReal(Op<double>::V(v1,v2));
}
return 0;
}
template<template<typename> class Op, bool intArifm=true>
ObjectBase* Arifm1(const ObjectList* input)
{
if(input->Size()!=1) return 0;
const ObjectBase *arg=input->At(0);
OBTypeM<Valuei,ObjectInt,ObjectString> i(arg);
OBTypeM<Valued,ObjectReal,ObjectString> r(arg);
bool isok;
// Integer arifmetic
isok=true;
if(i && intArifm)
{
int64_t v=i(&isok);
if(isok) return new ObjectInt(Op<int64_t>::V(v));
}
// Real arifmetic
isok=true;
if(r)
{
double v=r(&isok);
if(isok) return new ObjectReal(Op<double>::V(v));
}
return 0;
}

123
src/builtin.cpp

@ -1,123 +0,0 @@
#include <math.h>
#include "object.h"
class Val
{
double v;
public:
Val() = delete;
Val(Val&&) = delete;
Val(Val&) = delete;
Val(const OBType<ObjectInt>& i, const OBType<ObjectReal>& r) {v=r?r->Value():i->Value();}
Val(const OBType<ObjectReal>& r, const OBType<ObjectInt>& i) {v=r?r->Value():i->Value();}
operator double() const {return v;}
};
ObjectBase* Arifm_Add(const ObjectList* input)
{
if(input->Size()!=2) return 0;
const ObjectBase *arg1=input->At(0),*arg2=input->At(1);
OBType<ObjectInt> i1(arg1), i2(arg2);
OBType<ObjectReal> r1(arg1), r2(arg2);
if( !(i1 || r1) || !(i2 || r2) ) return 0;
// Integer arifmetic
if(i1 && i2) return new ObjectInt(i1->Value()+i2->Value());
// Real arifmetic
return new ObjectReal(Val(i1,r1)+Val(i2,r2));
}
ObjectBase* Arifm_Sub(const ObjectList* input)
{
if(input->Size()!=2) return 0;
const ObjectBase *arg1=input->At(0),*arg2=input->At(1);
OBType<ObjectInt> i1(arg1), i2(arg2);
OBType<ObjectReal> r1(arg1), r2(arg2);
if( !(i1 || r1) || !(i2 || r2) ) return 0;
// Integer arifmetic
if(i1 && i2) return new ObjectInt(i1->Value()-i2->Value());
// Real arifmetic
return new ObjectReal(Val(i1,r1)-Val(i2,r2));
}
ObjectBase* Arifm_Mul(const ObjectList* input)
{
if(input->Size()!=2) return 0;
const ObjectBase *arg1=input->At(0),*arg2=input->At(1);
OBType<ObjectInt> i1(arg1), i2(arg2);
OBType<ObjectReal> r1(arg1), r2(arg2);
if( !(i1 || r1) || !(i2 || r2) ) return 0;
// Integer arifmetic
if(i1 && i2) return new ObjectInt(i1->Value()*i2->Value());
// Real arifmetic
return new ObjectReal(Val(i1,r1)*Val(i2,r2));
}
ObjectBase* Arifm_Div(const ObjectList* input)
{
if(input->Size()!=2) return 0;
const ObjectBase *arg1=input->At(0),*arg2=input->At(1);
OBType<ObjectInt> i1(arg1), i2(arg2);
OBType<ObjectReal> r1(arg1), r2(arg2);
if( !(i1 || r1) || !(i2 || r2) ) return 0;
// Integer arifmetic
if(i1 && i2) return new ObjectInt(i1->Value()/i2->Value());
// Real arifmetic
return new ObjectReal(Val(i1,r1)/Val(i2,r2));
}
ObjectBase* Arifm_Pow(const ObjectList* input)
{
if(input->Size()!=2) return 0;
const ObjectBase *arg1=input->At(0),*arg2=input->At(1);
OBType<ObjectInt> i1(arg1), i2(arg2);
OBType<ObjectReal> r1(arg1), r2(arg2);
if( !(i1 || r1) || !(i2 || r2) ) return 0;
// Only real arifmetic
return new ObjectReal(pow(Val(i1,r1),Val(i2,r2)));
}
ObjectBase* Arifm_Neg(const ObjectList* input)
{
if(input->Size()!=1) return 0;
const ObjectBase *arg=input->At(0);
OBType<ObjectInt> i(arg);
OBType<ObjectReal> r(arg);
// Integer arifmetic
if(i) return new ObjectInt(-i->Value());
// Real arifmetic
if(r) return new ObjectReal(-r->Value());
return 0;
}
ObjectBase* Arifm_Pos(const ObjectList* input)
{
if(input->Size()!=1) return 0;
const ObjectBase *arg=input->At(0);
OBType<ObjectInt> i(arg);
OBType<ObjectReal> r(arg);
// Integer arifmetic
if(i) return new ObjectInt(i->Value());
// Real arifmetic
if(r) return new ObjectReal(r->Value());
return 0;
}

14
src/init.cpp

@ -134,13 +134,13 @@ int ParseOptions(int argc, char** argv, struct program_options& options)
int RegisterBuiltinFunctions() int RegisterBuiltinFunctions()
{ {
RegisterFunction("ADD",Arifm_Add); RegisterFunction("ADD",Arifm2<OpAdd>);
RegisterFunction("SUB",Arifm_Sub); RegisterFunction("SUB",Arifm2<OpSub>);
RegisterFunction("MUL",Arifm_Mul); RegisterFunction("MUL",Arifm2<OpMul>);
RegisterFunction("DIV",Arifm_Div); RegisterFunction("DIV",Arifm2<OpDiv>);
RegisterFunction("POW",Arifm_Pow); RegisterFunction("POW",Arifm2<OpPow,false>);
RegisterFunction("POS",Arifm_Pos); RegisterFunction("NEG",Arifm1<OpNeg>);
RegisterFunction("NEG",Arifm_Neg); RegisterFunction("POS",Arifm1<OpPos>);
RegisterFunction("GET",Get<ObjectList>); RegisterFunction("GET",Get<ObjectList>);
RegisterFunction("GET",Get<ObjectPair>); RegisterFunction("GET",Get<ObjectPair>);

Loading…
Cancel
Save