diff --git a/include/builtin.h b/include/builtin.h index 05a60e8..17d0b69 100644 --- a/include/builtin.h +++ b/include/builtin.h @@ -1,9 +1,92 @@ +#include #include "object.h" -ObjectBase* Arifm_Add(const ObjectList* input); -ObjectBase* Arifm_Sub(const ObjectList* input); -ObjectBase* Arifm_Mul(const ObjectList* input); -ObjectBase* Arifm_Div(const ObjectList* input); -ObjectBase* Arifm_Pow(const ObjectList* input); -ObjectBase* Arifm_Neg(const ObjectList* input); -ObjectBase* Arifm_Pos(const ObjectList* input); +template +struct Valued +{ + double operator ()(const O* q, bool* isok) {return q->Value();} +}; + +template<> +struct Valued +{ + double operator ()(const ObjectString* q, bool* isok) {double d=0; *isok=str2double(q->Value(),&d); return d;} +}; + +template +struct Valuei +{ + int64_t operator ()(const O* q, bool* isok) {return q->Value();} +}; + +template<> +struct Valuei +{ + int64_t operator ()(const ObjectString* q, bool* isok) {int64_t i=0; *isok=str2int(q->Value(),&i); return i;} +}; + + +template class OpAdd {public: static T V(T a1, T a2) {return a1+a2;}}; +template class OpSub {public: static T V(T a1, T a2) {return a1-a2;}}; +template class OpMul {public: static T V(T a1, T a2) {return a1*a2;}}; +template class OpDiv {public: static T V(T a1, T a2) {return a1/a2;}}; +template class OpPow {public: static T V(T a1, T a2) {return pow(a1,a2);}}; +template class OpNeg {public: static T V(T a) {return -a;}}; +template class OpPos {public: static T V(T a) {return +a;}}; + +template 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 i1(arg1), i2(arg2); + OBTypeM 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::V(v1,v2)); + } + + // Real arifmetic + isok=true; + if(r1 && r2) + { + double v1=r1(&isok),v2=r2(&isok); + if(isok) return new ObjectReal(Op::V(v1,v2)); + } + + return 0; +} + + +template class Op, bool intArifm=true> +ObjectBase* Arifm1(const ObjectList* input) +{ + if(input->Size()!=1) return 0; + const ObjectBase *arg=input->At(0); + OBTypeM i(arg); + OBTypeM r(arg); + bool isok; + + // Integer arifmetic + isok=true; + if(i && intArifm) + { + int64_t v=i(&isok); + if(isok) return new ObjectInt(Op::V(v)); + } + + // Real arifmetic + isok=true; + if(r) + { + double v=r(&isok); + if(isok) return new ObjectReal(Op::V(v)); + } + + return 0; +} diff --git a/src/builtin.cpp b/src/builtin.cpp deleted file mode 100644 index adabd3d..0000000 --- a/src/builtin.cpp +++ /dev/null @@ -1,123 +0,0 @@ -#include -#include "object.h" - -class Val -{ - double v; - public: - Val() = delete; - Val(Val&&) = delete; - Val(Val&) = delete; - Val(const OBType& i, const OBType& r) {v=r?r->Value():i->Value();} - Val(const OBType& r, const OBType& 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 i1(arg1), i2(arg2); - OBType 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 i1(arg1), i2(arg2); - OBType 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 i1(arg1), i2(arg2); - OBType 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 i1(arg1), i2(arg2); - OBType 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 i1(arg1), i2(arg2); - OBType 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 i(arg); - OBType 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 i(arg); - OBType r(arg); - - // Integer arifmetic - if(i) return new ObjectInt(i->Value()); - // Real arifmetic - if(r) return new ObjectReal(r->Value()); - - return 0; -} diff --git a/src/init.cpp b/src/init.cpp index 562380e..0701819 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -134,13 +134,13 @@ int ParseOptions(int argc, char** argv, struct program_options& options) int RegisterBuiltinFunctions() { - RegisterFunction("ADD",Arifm_Add); - RegisterFunction("SUB",Arifm_Sub); - RegisterFunction("MUL",Arifm_Mul); - RegisterFunction("DIV",Arifm_Div); - RegisterFunction("POW",Arifm_Pow); - RegisterFunction("POS",Arifm_Pos); - RegisterFunction("NEG",Arifm_Neg); + RegisterFunction("ADD",Arifm2); + RegisterFunction("SUB",Arifm2); + RegisterFunction("MUL",Arifm2); + RegisterFunction("DIV",Arifm2); + RegisterFunction("POW",Arifm2); + RegisterFunction("NEG",Arifm1); + RegisterFunction("POS",Arifm1); RegisterFunction("GET",Get); RegisterFunction("GET",Get);