static Box* _intNew(Box* val, Box* base) { if (isSubclass(val->cls, int_cls)) { RELEASE_ASSERT(!base, ""); BoxedInt* n = static_cast<BoxedInt*>(val); if (val->cls == int_cls) return n; return new BoxedInt(n->n); } else if (isSubclass(val->cls, str_cls)) { int base_n; if (!base) base_n = 10; else { RELEASE_ASSERT(base->cls == int_cls, ""); base_n = static_cast<BoxedInt*>(base)->n; } BoxedString* s = static_cast<BoxedString*>(val); RELEASE_ASSERT(s->size() == strlen(s->data()), ""); Box* r = PyInt_FromString(s->data(), NULL, base_n); if (!r) throwCAPIException(); return r; } else if (isSubclass(val->cls, unicode_cls)) { int base_n; if (!base) base_n = 10; else { RELEASE_ASSERT(base->cls == int_cls, ""); base_n = static_cast<BoxedInt*>(base)->n; } Box* r = PyInt_FromUnicode(PyUnicode_AS_UNICODE(val), PyUnicode_GET_SIZE(val), base_n); if (!r) throwCAPIException(); return r; } else if (val->cls == float_cls) { RELEASE_ASSERT(!base, ""); double d = static_cast<BoxedFloat*>(val)->d; return new BoxedInt(d); } else { RELEASE_ASSERT(!base, ""); static const std::string int_str("__int__"); Box* r = callattr(val, &int_str, CallattrFlags({.cls_only = true, .null_on_nonexistent = true }), ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL); if (!r) { fprintf(stderr, "TypeError: int() argument must be a string or a number, not '%s'\n", getTypeName(val)); raiseExcHelper(TypeError, ""); } if (!isSubclass(r->cls, int_cls) && !isSubclass(r->cls, long_cls)) { raiseExcHelper(TypeError, "__int__ returned non-int (type %s)", r->cls->tp_name); } return r; }
BoxedLong* _longNew(Box* val, Box* _base) { BoxedLong* rtn = new BoxedLong(); if (_base) { if (!isSubclass(_base->cls, int_cls)) raiseExcHelper(TypeError, "an integer is required"); int base = static_cast<BoxedInt*>(_base)->n; if (!isSubclass(val->cls, str_cls)) raiseExcHelper(TypeError, "long() can't convert non-string with explicit base"); BoxedString* s = static_cast<BoxedString*>(val); rtn = (BoxedLong*)PyLong_FromString(s->data(), NULL, base); checkAndThrowCAPIException(); } else { if (isSubclass(val->cls, long_cls)) { BoxedLong* l = static_cast<BoxedLong*>(val); if (val->cls == long_cls) return l; BoxedLong* rtn = new BoxedLong(); mpz_init_set(rtn->n, l->n); return rtn; } else if (isSubclass(val->cls, int_cls)) { mpz_init_set_si(rtn->n, static_cast<BoxedInt*>(val)->n); } else if (val->cls == str_cls) { llvm::StringRef s = static_cast<BoxedString*>(val)->s(); assert(s.data()[s.size()] == '\0'); int r = mpz_init_set_str(rtn->n, s.data(), 10); RELEASE_ASSERT(r == 0, ""); } else if (val->cls == float_cls) { mpz_init_set_si(rtn->n, static_cast<BoxedFloat*>(val)->d); } else { static BoxedString* long_str = static_cast<BoxedString*>(PyString_InternFromString("__long__")); Box* r = callattr(val, long_str, CallattrFlags({.cls_only = true, .null_on_nonexistent = true }), ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL); if (!r) { fprintf(stderr, "TypeError: long() argument must be a string or a number, not '%s'\n", getTypeName(val)); raiseExcHelper(TypeError, ""); } if (isSubclass(r->cls, int_cls)) { mpz_init_set_si(rtn->n, static_cast<BoxedInt*>(r)->n); } else if (!isSubclass(r->cls, long_cls)) { raiseExcHelper(TypeError, "__long__ returned non-long (type %s)", r->cls->tp_name); } else { return static_cast<BoxedLong*>(r); } } }