From da0c897a95d128c3eb85a99d49a81c1add5b88a3 Mon Sep 17 00:00:00 2001 From: Michael Uleysky Date: Fri, 5 Aug 2016 21:54:34 +1000 Subject: [PATCH] Error reporting in arifmetic and Get<> functions. Replace 0 on nullptr. --- include/builtin.h | 50 +++++++++++++++++++++++++++++++++++------------ include/common.h | 32 +++++++++++++++++------------- src/deptree.cpp | 42 +++++++++++++++++++-------------------- src/globals.cpp | 31 ++++++++--------------------- src/init.cpp | 2 +- src/main.cpp | 4 ++-- src/object.cpp | 4 ++-- 7 files changed, 89 insertions(+), 76 deletions(-) diff --git a/include/builtin.h b/include/builtin.h index 17d0b69..15becab 100644 --- a/include/builtin.h +++ b/include/builtin.h @@ -10,7 +10,7 @@ struct Valued template<> struct Valued { - double operator ()(const ObjectString* q, bool* isok) {double d=0; *isok=str2double(q->Value(),&d); return d;} + double operator ()(const ObjectString* q, bool* isok) {double d=0; if(!str2double(q->Value(),&d)) *isok=false; return d;} }; template @@ -22,7 +22,7 @@ struct Valuei template<> struct Valuei { - int64_t operator ()(const ObjectString* q, bool* isok) {int64_t i=0; *isok=str2int(q->Value(),&i); return i;} + int64_t operator ()(const ObjectString* q, bool* isok) {int64_t i=0; if(!str2int(q->Value(),&i)) *isok=false; return i;} }; @@ -37,36 +37,52 @@ 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; + if(input->Size()!=2) return new ObjectError("Arifmetic binary operator","incorrect number of arguments"); const ObjectBase *arg1=input->At(0),*arg2=input->At(1); OBTypeM i1(arg1), i2(arg2); OBTypeM r1(arg1), r2(arg2); - bool isok; + bool isok1=true, isok2=true; // 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)); + int64_t v1=i1(&isok1),v2=i2(&isok2); + if(isok1 && isok2) return new ObjectInt(Op::V(v1,v2)); } + isok1=isok2=true; // Real arifmetic - isok=true; if(r1 && r2) { - double v1=r1(&isok),v2=r2(&isok); - if(isok) return new ObjectReal(Op::V(v1,v2)); + double v1=r1(&isok1),v2=r2(&isok2); + if(isok1 && isok2) return new ObjectReal(Op::V(v1,v2)); + } + + // Analyze error + // Check first argument + switch(r1.Error()) + { + case(OBTypeErr::OK): if(!isok1) return new ObjectError("Arifmetic binary operator","failed conversion of first argument to double"); else break; + case(OBTypeErr::NULLPTR): return new ObjectError("Arifmetic binary operator","first argument is nullptr"); // Impossible case + case(OBTypeErr::TYPEMISMATCH): return new ObjectError("Arifmetic binary operator","first argument has incorrect type"); } - return 0; + // Firs argument is ok, check second + switch(r2.Error()) + { + case(OBTypeErr::OK): if(!isok2) return new ObjectError("Arifmetic binary operator","failed conversion of second argument to double"); else break; + case(OBTypeErr::NULLPTR): return new ObjectError("Arifmetic binary operator","second argument is nullptr"); // Impossible case + case(OBTypeErr::TYPEMISMATCH): return new ObjectError("Arifmetic binary operator","second argument has incorrect type"); + } + + return new ObjectError("Arifmetic binary operator","unknown error"); // Impossible case } template class Op, bool intArifm=true> ObjectBase* Arifm1(const ObjectList* input) { - if(input->Size()!=1) return 0; + if(input->Size()!=1) return new ObjectError("Arifmetic unary operator","incorrect number of arguments"); const ObjectBase *arg=input->At(0); OBTypeM i(arg); OBTypeM r(arg); @@ -88,5 +104,13 @@ ObjectBase* Arifm1(const ObjectList* input) if(isok) return new ObjectReal(Op::V(v)); } - return 0; + // Analyze error + switch(r.Error()) + { + case(OBTypeErr::OK): if(!isok) return new ObjectError("Arifmetic unary operator","failed conversion of argument to double"); else break; + case(OBTypeErr::NULLPTR): return new ObjectError("Arifmetic unary operator","argument is nullptr"); // Impossible case + case(OBTypeErr::TYPEMISMATCH): return new ObjectError("Arifmetic unary operator","argument has incorrect type"); + } + + return new ObjectError("Arifmetic unary operator","unknown error"); // Impossible case } diff --git a/include/common.h b/include/common.h index 79a257b..e5ae50c 100644 --- a/include/common.h +++ b/include/common.h @@ -39,7 +39,7 @@ class EXPORT ObjectBase protected: bool err; // No save by default - virtual const int8_t* Blob(size_t* size) const { *size=0; return 0; } + virtual const int8_t* Blob(size_t* size) const { *size=0; return nullptr; } virtual void DeallocBlob(const int8_t* ptr) const {}; ObjectBase():err(false) {} public: @@ -57,6 +57,7 @@ class EXPORT ObjectBase virtual std::string Dump() const {return "%"+Type()+"%";} }; +enum class OBTypeErr {OK,NULLPTR,TYPEMISMATCH}; // Template for checking and using ObjectBase derivative classes // Checking if arg is non-zero: if(OBType(arg).Exist()) @@ -71,11 +72,12 @@ class OBType OBType() = delete; OBType(OBType&&) = delete; OBType(OBType&) = delete; - OBType(const ObjectBase* arg):iszero(0==arg) {if(0==arg) p=0; else if(typeid(*arg)==typeid(O)) p=dynamic_cast(arg); else p=0;} + OBType(const ObjectBase* arg):iszero(nullptr==arg) {if(nullptr==arg) p=nullptr; else if(typeid(*arg)==typeid(O)) p=dynamic_cast(arg); else p=nullptr;} const O* operator->() const {return p;} - operator bool() const {return 0!=p;} + operator bool() const {return nullptr!=p;} operator const O*() const {return p;} bool Exist() const {return !iszero;} + OBTypeErr Error() const {if(iszero) return OBTypeErr::NULLPTR; else if(nullptr==p) return OBTypeErr::TYPEMISMATCH; else return OBTypeErr::OK;} }; @@ -110,7 +112,7 @@ class OBTypeM: public OBTypeM else return OBTypeM::template F(args...); } public: - OBTypeM(const ObjectBase* arg):OBTypeM(arg) {if(0==arg) right=false; else right=(typeid(*arg)==typeid(O1));} + OBTypeM(const ObjectBase* arg):OBTypeM(arg) {if(nullptr==arg) right=false; else right=(typeid(*arg)==typeid(O1));} operator bool() const {return right || OBTypeM::operator bool();} template bool Apply(Res& res, Args... args) const @@ -127,6 +129,7 @@ class OBTypeM: public OBTypeM else return OBTypeM::template F(args...); } bool Exist() const {return OBTypeM::Exist();} + OBTypeErr Error() const {if(!Exist()) return OBTypeErr::NULLPTR; else if(!operator bool()) return OBTypeErr::TYPEMISMATCH; else return OBTypeErr::OK;} }; // Partial instantiation of the bottom of recursion @@ -147,7 +150,7 @@ class OBTypeM void operator ()(Args... args) const {} template Res F(Args... args) const {return Res();} - bool Exist() const {return 0!=p;} + bool Exist() const {return nullptr!=p;} }; @@ -261,17 +264,17 @@ public: std::string Dump() const override { return Name()+"="+val->Dump(); } // Own functions - bool Exist() const {return 0!=val.get();} + bool Exist() const {return nullptr!=val.get();} ObjectBase* Get(const std::string& gname) const { if(gname==name) return val->Copy(); - else return 0; + else return new ObjectError("ObjectPair Get","pair has name "+name+" not "+gname); } // This function is same as Get but return pointer on constant object const ObjectBase* Find(const std::string& gname) const { if(gname==name) return val.get(); - else return 0; + else return nullptr; } std::string Name() const {return name;} void SetPair(const std::string& n, ObjectBase* v) {if(!Exist()) {name=n; val.reset(v);}} @@ -321,7 +324,7 @@ public: ObjectBase* Get(const std::string& gname) const { const ObjectBase* p=Find(gname); - return (0==p)?0:p->Copy(); + return (nullptr==p)?new ObjectError("ObjectList Get","name "+gname+" not found in list"):p->Copy(); } // This function is same as Get but return pointer on constant object const ObjectBase* Find(const std::string& gname) const @@ -329,14 +332,14 @@ public: const ObjectBase* p; for(auto& i: *vals) { - p=0; + p=nullptr; OBType pair(i); OBType list(i); if(pair) p=pair->Find(gname); else if(list) p=list->Find(gname); - if(0!=p) return p; + if(nullptr!=p) return p; } - return 0; + return nullptr; } ListValues::size_type Size() const {return vals->size();} ObjectList* PushBack(ObjectBase* p) {vals->push_back(p); return this;} @@ -354,10 +357,11 @@ EXPORT int LoadModule(const std::string& name, const void* p, const std::string& template ObjectBase* Get(const ObjectList* input) { - if(input->Size()!=2) return 0; + if(input->Size()!=2) return new ObjectError("GET","incorrect number of arguments"); OBType ob(input->At(0)); OBType name(input->At(1)); - if(!(ob && name)) return 0; + if(!name) return new ObjectError("GET","second argument is not ObjectString"); + if(!ob) return new ObjectError("GET","incorrect type of first argument"); return ob->Get(name->Value()); } diff --git a/src/deptree.cpp b/src/deptree.cpp index da842fc..0b75e9f 100644 --- a/src/deptree.cpp +++ b/src/deptree.cpp @@ -281,14 +281,14 @@ void* TreeEvaluateM(void* arg) // Begin critical section (access to root) pthread_mutex_lock(&p->root_mtx); // Check, if all done, or error happens? - if(0==p->root->childrens.size() || 0!=p->exitcode) {pthread_mutex_unlock(&p->root_mtx); return 0;} + if(0==p->root->childrens.size() || 0!=p->exitcode) {pthread_mutex_unlock(&p->root_mtx); return nullptr;} // End critical section pthread_mutex_unlock(&p->root_mtx); // Begin critical section (access to leafs) pthread_mutex_lock(&p->leaf_mtx); // Check, if some work available? - if(0==p->leafs.size()) {pthread_mutex_unlock(&p->leaf_mtx); nanosleep(&skip,0); continue;} + if(0==p->leafs.size()) {pthread_mutex_unlock(&p->leaf_mtx); nanosleep(&skip,nullptr); continue;} // Select working node leaf=*(p->leafs.begin()); // and remove its from list @@ -307,12 +307,12 @@ void* TreeEvaluateM(void* arg) COUT(ERROR)<<" in instruction save at line "<exitcode=1; - return 0; + return nullptr; } if(!Save(ol.get())) { p->exitcode=1; - return 0; + return nullptr; } // This leaf can have only one parent - root // Begin critical section (access to root) @@ -333,12 +333,12 @@ void* TreeEvaluateM(void* arg) COUT(ERROR)<<" in instruction print at line "<exitcode=1; - return 0; + return nullptr; } if(!Print(ol.get())) { p->exitcode=1; - return 0; + return nullptr; } // Begin critical section (access to root) @@ -363,7 +363,7 @@ void* TreeEvaluateM(void* arg) COUT(ERROR)<<" in definition of variable "<name<<" at line "<exitcode=1; - return 0; + return nullptr; } // Begin critical section (access to tree structure) @@ -390,7 +390,7 @@ void* TreeEvaluateM(void* arg) leaf->parents.clear(); delete leaf; } - return 0; + return nullptr; } @@ -419,13 +419,13 @@ void* TreeEvaluate(void* arg) COUT(ERROR)<<" in instruction save at line "<exitcode=1; - return 0; + return nullptr; } // eob is evaluated object if(!Save(ol.get())) { p->exitcode=1; - return 0; + return nullptr; } // This leaf can have only one parent - root (*leaf->parents.begin())->childrens.erase(leaf); @@ -442,12 +442,12 @@ void* TreeEvaluate(void* arg) COUT(ERROR)<<" in instruction print at line "<exitcode=1; - return 0; + return nullptr; } if(!Print(ol.get())) { p->exitcode=1; - return 0; + return nullptr; } // This leaf can have only one parent - root (*leaf->parents.begin())->childrens.erase(leaf); @@ -466,7 +466,7 @@ void* TreeEvaluate(void* arg) COUT(ERROR)<<" in definition of variable "<name<<" at line "<exitcode=1; - return 0; + return nullptr; } for(auto& i:leaf->parents) @@ -483,7 +483,7 @@ void* TreeEvaluate(void* arg) leaf->parents.clear(); delete leaf; } - return 0; + return nullptr; } @@ -499,16 +499,16 @@ int DepTree::EvaluateTree(unsigned int nthreads) { pthread_t* threads=new pthread_t[nthreads-1]; p.root=this; - pthread_mutex_init(&p.leaf_mtx,0); - pthread_mutex_init(&p.root_mtx,0); - pthread_mutex_init(&p.vars_mtx,0); - pthread_mutex_init(&p.prsv_mtx,0); - pthread_mutex_init(&p.tree_mtx,0); + pthread_mutex_init(&p.leaf_mtx,nullptr); + pthread_mutex_init(&p.root_mtx,nullptr); + pthread_mutex_init(&p.vars_mtx,nullptr); + pthread_mutex_init(&p.prsv_mtx,nullptr); + pthread_mutex_init(&p.tree_mtx,nullptr); while(0!=p.root->parents.size()) p.root=*(p.root->parents.begin()); - for(unsigned int i=0;i