Ejemplo n.º 1
0
void marshal_from_sexp<SmokeClassWrapper>(MethodCall *m)
{
  SEXP v = m->sexp();
  SmokeType type = m->type();
  SmokeObject *o = NULL /*, *coerced = NULL */;

  /* Not clear if we want to (partially) support this complicated C++ feature
  if (v != R_NilValue) {
    o = SmokeObject::fromSexp(v);
    if (!o->instanceOf(type.className())) {
      // attempt implicit conversion
      coerced = o->convertImplicitly(type);
      if (coerced)
        o = coerced;
      else error("Failed to coerce an instance of type '%s' to '%s'",
                 o->className(), type.className());
    }
  }
  */
  
  o = from_sexp<SmokeObject *>(v, type);
  void *ptr = o ? o->castPtr(type.className(),
                             m->returning() && !type.fitsStack()) : NULL;
  setItemValue(m, ptr);

  /*
  m->marshal();

  if (coerced)
    delete coerced;
  */
  
  return;
}
Ejemplo n.º 2
0
/* C++ compilers select overloaded methods by ranking each argument in
   terms of its implicit conversions. There are three different types
   of implicit conversions: standard, user and ellipsis. We only
   consider the former, as the others probably are not relevant for
   Qt. Within standard conversions, there are three ranks: exact,
   promotion and conversion. We assign these scores 3, 2 and 1,
   respectively, while 0 indicates no conversion and -1 indicates an
   error (e.g. unsupported type). The method with better or same
   ranks for all of its parameters is selected. If there is a tie for
   the best method, there is an error (in our code).
*/
int scoreArg_basetype(SEXP arg, const SmokeType &type) {
  int score = 0;
  SEXP value = arg;
  int rtype = TYPEOF(value);
  unsigned short elem = type.elem();
  switch(rtype) { // try the simple cases first
  case RAWSXP:
    switch(elem) {
    case Smoke::t_uchar:
      score = 3;
      break;
    case Smoke::t_short:
    case Smoke::t_ushort:
      score = 2;
      break;
    case Smoke::t_int:
    case Smoke::t_uint:
    case Smoke::t_long:
    case Smoke::t_ulong:
    case Smoke::t_float:
    case Smoke::t_double:
      score = 1;
      break;
    default:
      break;
    }
    break;
  case INTSXP:
    switch(elem) {
    case Smoke::t_enum:
      if (inherits(value, "QtEnum"))
        score = 2;
      else score = 1;
      break;
    case Smoke::t_int:
      score = 3;
      break;
    case Smoke::t_uint:
      if (inherits(value, "QtEnum")) {
        score = 3; // favor QFlags over enums
        break;
      }
    case Smoke::t_long:
    case Smoke::t_ulong:
    case Smoke::t_float:
    case Smoke::t_double:
      score = 2;
      break;
    case Smoke::t_short:
    case Smoke::t_ushort:
    case Smoke::t_uchar:
      score = 1;
      break;
    default:
      break;
    }
    break;
  case REALSXP:
    switch(elem) {
    case Smoke::t_double:
      score = 3;
      break;
    case Smoke::t_float:
    case Smoke::t_uint: // to distinguish int/uint
      score = 2;
      break;
    case Smoke::t_int:
    case Smoke::t_long:
    case Smoke::t_ulong:
    case Smoke::t_short:
    case Smoke::t_ushort:
    case Smoke::t_uchar:
    case Smoke::t_enum:
      score = 1;
      break;
    default:
      break;
    }
    break;
  case STRSXP:
    if (elem == Smoke::t_char && strlen(CHAR(asChar(value))) == 1)
      score = 2;
    break;
  case ENVSXP:
    if (elem == Smoke::t_class) {
      SmokeObject *o = SmokeObject::fromSexp(value);
      if (o) {
        const char *smokeClass = type.className();
        if (o->className() == smokeClass)
          score = 3;
        else if (o->instanceOf(smokeClass))
          score = 2;
        /* Not clear if we want to support this C++ feature
        else {
          Method *m = Class::fromSmokeType(type)->findImplicitConverter(o);
          if (m) {
            score = 1;
            delete m;
          }
        }
        */
      }
    }
    break;
  case NILSXP:
    if (type.isPtr())
      score = 1;
    break;
  default:
    break;
  }
  return score;
}