Skip to content

Commit

Permalink
Revised exception messages
Browse files Browse the repository at this point in the history
  • Loading branch information
coatless committed Apr 14, 2017
1 parent a67d16a commit ba4403d
Show file tree
Hide file tree
Showing 16 changed files with 181 additions and 60 deletions.
21 changes: 20 additions & 1 deletion ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
2017-04-14 James J Balamuta <balamut2@illinois.edu>

* inst/include/Rcpp/Environment.h: Modified formatting of new exception
messages to be more concise.
* inst/include/Rcpp/exceptions.h: idem
* inst/include/Rcpp/Function.h: idem
* inst/include/Rcpp/Promise.h: idem
* inst/include/Rcpp/String.h: idem
* inst/include/Rcpp/Symbol.h: idem
* inst/include/Rcpp/XPtr.h: idem
* inst/include/Rcpp/as.h: idem
* inst/include/Rcpp/r_cast.h: idem
* inst/include/Rcpp/api/meat/DottedPairImpl.h: idem
* inst/include/Rcpp/internal/export.h: idem
* inst/include/Rcpp/proxy/DottedPairProxy.h: idem
* inst/include/Rcpp/vector/MatrixColumn.h: idem
* inst/include/Rcpp/vector/MatrixRow.h: idem
* inst/include/Rcpp/vector/Vector.h: idem

2017-04-11 Dirk Eddelbuettel <edd@debian.org>

* inst/inst/unitTests/testRcppClass/src/init.c (R_init_testRcppClass): Call
Expand Down Expand Up @@ -43,6 +62,7 @@
* inst/include/Rcpp/macros/macros.h: Idem
* inst/unitTests/cpp/exceptions.cpp: Idem
* inst/unitTests/runit.exceptions.R: Idem

2017-04-10 James J Balamuta <balamut2@illinois.edu>

* inst/include/Rcpp/exceptions.h: Added new exception class generation
Expand All @@ -55,7 +75,6 @@
* inst/include/Rcpp/Symbol.h: idem
* inst/include/Rcpp/XPtr.h: idem
* inst/include/Rcpp/as.h: idem
* inst/include/Rcpp/exceptions.h: idem
* inst/include/Rcpp/r_cast.h: idem
* inst/include/Rcpp/api/meat/DottedPairImpl.h: idem
* inst/include/Rcpp/internal/export.h: idem
Expand Down
5 changes: 4 additions & 1 deletion inst/include/Rcpp/Environment.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ namespace Rcpp{
Shield<SEXP> res( Rcpp_eval( Rf_lang2( asEnvironmentSym, x ) ) );
return res ;
} catch( const eval_error& ex){
throw not_compatible( "Cannot convert to environment (%s -> ENVSXP).", Rf_type2char(TYPEOF(x))) ;
const char* fmt =
"Cannot convert object to an environment: "
"[type:%s; target=ENVSXP].";
throw not_compatible(fmt, Rf_type2char(TYPEOF(x))) ;
}
}

Expand Down
5 changes: 4 additions & 1 deletion inst/include/Rcpp/Function.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ namespace Rcpp{
Storage::set__(x);
break;
default:
throw not_compatible("cannot convert %s object to function", Rf_type2char(TYPEOF(x))) ;
const char* fmt =
"Cannot convert object to a function:"
"[type=%s; target=CLOSXP, SPECIALSXP, or BUILTINSXP].";
throw not_compatible(fmt, Rf_type2char(TYPEOF(x))) ;
}
}

Expand Down
6 changes: 4 additions & 2 deletions inst/include/Rcpp/Promise.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ namespace Rcpp{
RCPP_GENERATE_CTOR_ASSIGN(Promise_Impl)

Promise_Impl( SEXP x){
if( TYPEOF(x) != PROMSXP)
throw not_compatible("Not a promise. Object is of type %s instead of PROMSXP.", Rf_type2char(TYPEOF(x))) ;
if( TYPEOF(x) != PROMSXP){
const char* fmt = "Not a promise: [type = %s].";
throw not_compatible(fmt, Rf_type2char(TYPEOF(x))) ;
}
Storage::set__(x) ;
}

Expand Down
10 changes: 8 additions & 2 deletions inst/include/Rcpp/String.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,14 @@ namespace Rcpp {
data = charsxp;
}

if (::Rf_isString(data) && ::Rf_length(data) != 1)
throw ::Rcpp::not_compatible("Expecting a single string value. Received %s object with length %i.", Rf_type2char(TYPEOF(data)), ::Rf_length(data));
if (::Rf_isString(data) && ::Rf_length(data) != 1){
const char* fmt =
"Expecting a single string value: [type=%s; extent=%i].";
throw ::Rcpp::not_compatible(fmt,
Rf_type2char(TYPEOF(data)),
::Rf_length(data));

}

valid = true;
buffer_ready = false;
Expand Down
4 changes: 3 additions & 1 deletion inst/include/Rcpp/Symbol.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ namespace Rcpp{
break ;
}
default:
throw not_compatible("Cannot object convert to symbol (%s -> SYMSXP)", Rf_type2char(type)) ;
const char* fmt =
"Cannot convert object to a symbol (%s -> SYMSXP).";
throw not_compatible(fmt, Rf_type2char(type)) ;
}
}

Expand Down
6 changes: 4 additions & 2 deletions inst/include/Rcpp/XPtr.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,10 @@ class XPtr :
* @param xp external pointer to wrap
*/
explicit XPtr(SEXP x, SEXP tag = R_NilValue, SEXP prot = R_NilValue) {
if( TYPEOF(x) != EXTPTRSXP )
throw ::Rcpp::not_compatible( "Expecting an external pointer. Object was a %s instead of EXTPTRSXP", Rf_type2char(TYPEOF(x)) ) ;
if( TYPEOF(x) != EXTPTRSXP ) {
const char* fmt = "Expecting an external pointer: [type=%s].";
throw ::Rcpp::not_compatible(fmt, Rf_type2char(TYPEOF(x)) ) ;
}
Storage::set__(x) ;
R_SetExternalPtrTag( x, tag ) ;
R_SetExternalPtrProtected( x, prot ) ;
Expand Down
22 changes: 19 additions & 3 deletions inst/include/Rcpp/api/meat/DottedPairImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,12 @@ namespace Rcpp{
} else {
if( ref.isNULL( ) ) throw index_out_of_bounds() ;

if( static_cast<R_xlen_t>(index) > ::Rf_xlength(ref.get__()) ) throw index_out_of_bounds("index is out of bounds. Requested %i with %i available", static_cast<R_xlen_t>(index), ::Rf_xlength(ref.get__()) ) ;
if( static_cast<R_xlen_t>(index) > ::Rf_xlength(ref.get__()) ) {
const char* fmt = "Index is out of bounds: [index=%s; extent=%s].";
throw index_out_of_bounds(fmt,
static_cast<R_xlen_t>(index),
::Rf_xlength(ref.get__()) ) ;
}

size_t i=1;
SEXP x = ref.get__() ;
Expand All @@ -70,7 +75,12 @@ namespace Rcpp{
template <typename T>
void DottedPairImpl<CLASS>::replace( const int& index, const T& object ) {
CLASS& ref = static_cast<CLASS&>(*this) ;
if( static_cast<R_xlen_t>(index) >= ::Rf_xlength(ref.get__()) ) throw index_out_of_bounds("index is out of bounds. Requested %i with %i available", static_cast<R_xlen_t>(index), ::Rf_xlength(ref.get__()) ) ;
if( static_cast<R_xlen_t>(index) >= ::Rf_xlength(ref.get__()) ) {
const char* fmt = "Index is out of bounds: [index=%s; extent=%s].";
throw index_out_of_bounds(fmt,
static_cast<R_xlen_t>(index),
::Rf_xlength(ref.get__()) ) ;
}

Shield<SEXP> x( pairlist( object ) );
SEXP y = ref.get__() ;
Expand All @@ -84,7 +94,13 @@ namespace Rcpp{
template <typename CLASS>
void DottedPairImpl<CLASS>::remove( const size_t& index ) {
CLASS& ref = static_cast<CLASS&>(*this) ;
if( static_cast<R_xlen_t>(index) >= Rf_xlength(ref.get__()) ) throw index_out_of_bounds("index is out of bounds. Requested %i with %i available", static_cast<R_xlen_t>(index), ::Rf_xlength(ref.get__()) ) ;
if( static_cast<R_xlen_t>(index) >= Rf_xlength(ref.get__()) ) {
const char* fmt = "Index is out of bounds: [index=%s; extent=%s].";
throw index_out_of_bounds(fmt,
static_cast<R_xlen_t>(index),
::Rf_xlength(ref.get__()) ) ;
}

if( index == 0 ){
ref.set__( CDR( ref.get__() ) ) ;
} else{
Expand Down
23 changes: 16 additions & 7 deletions inst/include/Rcpp/as.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ namespace Rcpp {
namespace internal {

template <typename T> T primitive_as(SEXP x) {
if (::Rf_length(x) != 1) throw ::Rcpp::not_compatible("Expecting a single value. Object contained %i values.", ::Rf_length(x));
if (::Rf_length(x) != 1) {
const char* fmt = "Expecting a single value: [extent=%i].";
throw ::Rcpp::not_compatible(fmt, ::Rf_length(x));
}
const int RTYPE = ::Rcpp::traits::r_sexptype_traits<T>::rtype;
Shield<SEXP> y(r_cast<RTYPE>(x));
typedef typename ::Rcpp::traits::storage_type<RTYPE>::type STORAGE;
Expand All @@ -43,10 +46,14 @@ namespace Rcpp {

inline const char* check_single_string(SEXP x) {
if (TYPEOF(x) == CHARSXP) return CHAR(x);
if (! ::Rf_isString(x))
throw ::Rcpp::not_compatible("Expecting a string. Received %s instead of CHARSXP or STRSXP.", Rf_type2char(TYPEOF(x)));
if (Rf_length(x) != 1)
throw ::Rcpp::not_compatible("Expecting a single value. Object contained %i values.", ::Rf_length(x));
if (! ::Rf_isString(x)) {
const char* fmt = "Expecting a string: [type=%s].";
throw ::Rcpp::not_compatible(fmt, Rf_type2char(TYPEOF(x)));
}
if (Rf_length(x) != 1) {
const char* fmt = "Expecting a single value: [extent=%i].";
throw ::Rcpp::not_compatible(fmt, ::Rf_length(x));
}
return CHAR(STRING_ELT(::Rcpp::r_cast<STRSXP>(x), 0));
}

Expand All @@ -66,10 +73,12 @@ namespace Rcpp {

template <typename T> T as(SEXP x, ::Rcpp::traits::r_type_RcppString_tag) {
if (! ::Rf_isString(x)) {
throw ::Rcpp::not_compatible("Expecting a string. Received %s instead of STRSXP.", Rf_type2char(TYPEOF(x)));
const char* fmt = "Expecting a string: [type=%s].";
throw ::Rcpp::not_compatible(fmt, Rf_type2char(TYPEOF(x)));
}
if (Rf_length(x) != 1) {
throw ::Rcpp::not_compatible("Expecting a single value. Object contained %i values.", ::Rf_length(x));
const char* fmt = "Expecting a single value: [extent=%i].";
throw ::Rcpp::not_compatible(fmt, ::Rf_length(x));
}
return STRING_ELT(::Rcpp::r_cast<STRSXP>(x), 0);
}
Expand Down
38 changes: 19 additions & 19 deletions inst/include/Rcpp/exceptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,27 +157,27 @@ namespace Rcpp {
virtual const char* what() const throw() { return __MESSAGE__ ; } \
} ;

RCPP_SIMPLE_EXCEPTION_CLASS(not_a_matrix, "not a matrix")
RCPP_SIMPLE_EXCEPTION_CLASS(parse_error, "parse error")
RCPP_SIMPLE_EXCEPTION_CLASS(not_s4, "not an S4 object") // #nocov start
RCPP_SIMPLE_EXCEPTION_CLASS(not_reference, "not an S4 object of a reference class")
RCPP_SIMPLE_EXCEPTION_CLASS(not_initialized, "C++ object not initialized (missing default constructor?)")
RCPP_SIMPLE_EXCEPTION_CLASS(no_such_function, "no such function")
RCPP_SIMPLE_EXCEPTION_CLASS(unevaluated_promise, "promise not yet evaluated")

RCPP_EXCEPTION_CLASS(no_such_slot, std::string("no such slot: ") + message )
RCPP_EXCEPTION_CLASS(S4_creation_error, std::string("error creating object of S4 class: ") + message )
RCPP_EXCEPTION_CLASS(reference_creation_error, std::string("error creating object of reference class: ") + message )
RCPP_EXCEPTION_CLASS(no_such_binding, std::string("no such binding: '") + message + "'" )
RCPP_EXCEPTION_CLASS(binding_not_found, std::string("binding not found: '") + message + "'" )
RCPP_EXCEPTION_CLASS(binding_is_locked, std::string("binding is locked: '") + message + "'" )
RCPP_EXCEPTION_CLASS(no_such_namespace, std::string("no such namespace: '") + message + "'" )
RCPP_EXCEPTION_CLASS(function_not_exported, std::string("function not exported: ") + message)
RCPP_SIMPLE_EXCEPTION_CLASS(not_a_matrix, "Not a matrix.")
RCPP_SIMPLE_EXCEPTION_CLASS(parse_error, "Parse error.")
RCPP_SIMPLE_EXCEPTION_CLASS(not_s4, "Not an S4 object.") // #nocov start
RCPP_SIMPLE_EXCEPTION_CLASS(not_reference, "Not an S4 object of a reference class.")
RCPP_SIMPLE_EXCEPTION_CLASS(not_initialized, "C++ object not initialized. (Missing default constructor?)")
RCPP_SIMPLE_EXCEPTION_CLASS(no_such_function, "No such function.")
RCPP_SIMPLE_EXCEPTION_CLASS(unevaluated_promise, "Promise not yet evaluated.")

RCPP_EXCEPTION_CLASS(no_such_slot, std::string("No such slot: ") + message + "." )
RCPP_EXCEPTION_CLASS(S4_creation_error, std::string("Error creating object of S4 class: ") + message + "." )
RCPP_EXCEPTION_CLASS(reference_creation_error, std::string("Error creating object of reference class: ") + message + ".")
RCPP_EXCEPTION_CLASS(no_such_binding, std::string("No such binding: '") + message + "'." )
RCPP_EXCEPTION_CLASS(binding_not_found, std::string("Binding not found: '") + message + "'." )
RCPP_EXCEPTION_CLASS(binding_is_locked, std::string("Binding is locked: '") + message + "'." )
RCPP_EXCEPTION_CLASS(no_such_namespace, std::string("No such namespace: '") + message + "'." )
RCPP_EXCEPTION_CLASS(function_not_exported, std::string("Function not exported: ") + message + "." )
RCPP_EXCEPTION_CLASS(eval_error, message )
RCPP_EXCEPTION_CLASS(not_a_closure, std::string("not a closure. Object is of type ") + message + "." )
RCPP_EXCEPTION_CLASS(not_a_closure, std::string("Not a closure: [type=") + message + "]." )

RCPP_ADVANCED_EXCEPTION_CLASS(not_compatible, "not compatible")
RCPP_ADVANCED_EXCEPTION_CLASS(index_out_of_bounds, "index out of bounds") // #nocov end
RCPP_ADVANCED_EXCEPTION_CLASS(not_compatible, "Not compatible.")
RCPP_ADVANCED_EXCEPTION_CLASS(index_out_of_bounds, "Index out of bounds.") // #nocov end

#undef RCPP_SIMPLE_EXCEPTION_CLASS
#undef RCPP_EXCEPTION_CLASS
Expand Down
13 changes: 11 additions & 2 deletions inst/include/Rcpp/internal/export.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,12 @@ namespace Rcpp{

template <typename InputIterator, typename value_type>
void export_range__dispatch( SEXP x, InputIterator first, ::Rcpp::traits::r_type_string_tag ) {
if( ! ::Rf_isString( x) ) throw ::Rcpp::not_compatible( "Expecting a string vector. Object was of type %s instead of STRXP.", Rf_type2char(TYPEOF(x)) ) ;
if( ! ::Rf_isString( x) ) {
const char* fmt = "Expecting a string vector: "
"[type=%s; required=STRSXP].";
throw ::Rcpp::not_compatible(fmt, Rf_type2char(TYPEOF(x)) ) ;
}

R_xlen_t n = ::Rf_xlength(x) ;
for( R_xlen_t i=0; i<n; i++, ++first ){
*first = as_string_elt<typename std::iterator_traits<InputIterator>::value_type> ( x, i ) ;
Expand Down Expand Up @@ -133,7 +138,11 @@ namespace Rcpp{

template <typename T, typename value_type>
void export_indexing__dispatch( SEXP x, T& res, ::Rcpp::traits::r_type_string_tag ) {
if( ! ::Rf_isString( x) ) throw Rcpp::not_compatible( "Expecting a string vector. Object was of type %s instead of STRXP.", Rf_type2char(TYPEOF(x)) ) ;
if( ! ::Rf_isString( x) ) {
const char* fmt = "Expecting a string vector: "
"[type=%s; required=STRSXP].";
throw ::Rcpp::not_compatible(fmt, Rf_type2char(TYPEOF(x)) ) ;
}
R_xlen_t n = ::Rf_xlength(x) ;
for( R_xlen_t i=0; i<n; i++ ){
res[i] = as_string_elt< value_type >( x, i) ;
Expand Down
12 changes: 10 additions & 2 deletions inst/include/Rcpp/proxy/DottedPairProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ class DottedPairProxyPolicy {
class DottedPairProxy : public GenericProxy<DottedPairProxy> {
public:
DottedPairProxy( CLASS& v, int index_ ): node(R_NilValue){
if( index_ >= v.length() ) throw index_out_of_bounds("index out of bounds. Requested element %i when object has %i elements.", index_, v.length() ) ;
if( index_ >= v.length() ) {
const char* fmt = "Index is out of bounds: "
"[index=%s; extent=%s].";
throw index_out_of_bounds(fmt, index_, v.length() ) ;
}
SEXP x = v ; /* implicit conversion */
for( int i = 0; i<index_; i++, x = CDR(x) ) ;
node = x ;
Expand Down Expand Up @@ -72,7 +76,11 @@ class DottedPairProxyPolicy {
class const_DottedPairProxy : public GenericProxy<const_DottedPairProxy>{
public:
const_DottedPairProxy( const CLASS& v, int index_ ): node(R_NilValue){
if( index_ >= v.length() ) throw index_out_of_bounds("index out of bounds. Requested element %i when object has %i elements.", index_, v.length() ) ;
if( index_ >= v.length() ) {
const char* fmt = "Index is out of bounds: "
"[index=%s; extent=%s].";
throw index_out_of_bounds(fmt, index_, v.length() ) ;
}
SEXP x = v ; /* implicit conversion */
for( int i = 0; i<index_; i++, x = CDR(x) ) ;
node = x ;
Expand Down
14 changes: 10 additions & 4 deletions inst/include/Rcpp/r_cast.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ namespace Rcpp {
SEXP funSym = Rf_install(fun);
res = Rcpp_eval(Rf_lang2(funSym, x));
} catch( eval_error& e){
throw not_compatible("Could not convert using R function: %s.", fun);
const char* fmt = "Could not convert using R function: %s.";
throw not_compatible(fmt, fun);
}
return res; // #nocov end
}
Expand All @@ -42,7 +43,9 @@ namespace Rcpp {
// is different from the SEXP type of x
template <int TARGET>
SEXP r_true_cast( SEXP x) {
throw not_compatible( "Not compatible target with SEXP (%s -> %s).", Rf_type2char(TYPEOF(x)), Rf_type2char(TARGET));
const char* fmt = "Not compatible conversion to target: "
"[type=%s; target=%s].";
throw not_compatible(fmt, Rf_type2char(TYPEOF(x)), Rf_type2char(TARGET));
return x; // makes solaris happy
}

Expand All @@ -57,7 +60,9 @@ namespace Rcpp {
case INTSXP:
return Rf_coerceVector(x, RTYPE);
default:
throw ::Rcpp::not_compatible("Not compatible with requested type (%s -> %s).", Rf_type2char(TYPEOF(x)), Rf_type2char(RTYPE));
const char* fmt = "Not compatible with requested type: "
"[type=%s; target=%s].";
throw ::Rcpp::not_compatible(fmt, Rf_type2char(TYPEOF(x)), Rf_type2char(RTYPE));
} // #nocov end
return R_NilValue; /* -Wall */
}
Expand Down Expand Up @@ -103,7 +108,8 @@ namespace Rcpp {
case SYMSXP:
return Rf_ScalarString( PRINTNAME( x ) );
default:
throw ::Rcpp::not_compatible("Not compatible requested type (%s -> STRSXP).", Rf_type2char(TYPEOF(x)));
const char* fmt = "Not compatible with STRSXP: [type=%s].";
throw ::Rcpp::not_compatible(fmt, Rf_type2char(TYPEOF(x)));
}
return R_NilValue; /* -Wall */
}
Expand Down
18 changes: 15 additions & 3 deletions inst/include/Rcpp/vector/MatrixColumn.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,23 @@ class MatrixColumn : public VectorBase<RTYPE,true,MatrixColumn<RTYPE> > {
start(parent.begin() + static_cast<R_xlen_t>(i) * n ),
const_start(const_cast<const MATRIX&>(parent).begin() + static_cast<R_xlen_t>(i) * n)
{
if( i < 0 || i >= parent.ncol() ) throw index_out_of_bounds("index out of bounds. Requested column %i out of %i columns.", i, parent.ncol()) ;
if( i < 0 || i >= parent.ncol() ) {
const char* fmt = "Index is out of bounds: "
"[index=%s; column extent=%s].";
throw index_out_of_bounds(fmt, i, parent.ncol()) ;
}
}

MatrixColumn( const MATRIX& parent, int i ) :
n(parent.nrow()),
start( const_cast<MATRIX&>(parent).begin() + static_cast<R_xlen_t>(i) * n ),
const_start(parent.begin() + static_cast<R_xlen_t>(i) * n)
{
if( i < 0 || i >= parent.ncol() ) throw index_out_of_bounds("index out of bounds. Requested column %i out of %i columns.", i, parent.ncol()) ;
if( i < 0 || i >= parent.ncol() ) {
const char* fmt = "Index is out of bounds: "
"[index=%s; column extent=%s].";
throw index_out_of_bounds(fmt, i, parent.ncol()) ;
}
}

MatrixColumn( const MatrixColumn& other ) :
Expand Down Expand Up @@ -115,7 +123,11 @@ class ConstMatrixColumn : public VectorBase<RTYPE,true,ConstMatrixColumn<RTYPE>
n(parent.nrow()),
const_start(parent.begin() + i *n)
{
if( i < 0 || i >= parent.ncol() ) throw index_out_of_bounds("index out of bounds. Requested column %i out of %i columns.", i, parent.ncol()) ;
if( i < 0 || i >= parent.ncol() ) {
const char* fmt = "Index is out of bounds: "
"[index=%s; column extent=%s].";
throw index_out_of_bounds(fmt, i, parent.ncol()) ;
}
}

ConstMatrixColumn( const ConstMatrixColumn& other ) :
Expand Down
Loading

0 comments on commit ba4403d

Please sign in to comment.