void raise3(Box* arg0, Box* arg1, Box* arg2) { // TODO switch this to PyErr_Normalize if (isSubclass(arg0->cls, type_cls)) { BoxedClass* c = static_cast<BoxedClass*>(arg0); if (isSubclass(c, BaseException)) { Box* exc_obj; if (arg1 != None) exc_obj = exceptionNew2(c, arg1); else exc_obj = exceptionNew1(c); raiseRaw(ExcInfo(c, exc_obj, arg2)); } } if (isSubclass(arg0->cls, BaseException)) { if (arg1 != None) raiseExcHelper(TypeError, "instance exception may not have a separate value"); raiseRaw(ExcInfo(arg0->cls, arg0, arg2)); } raiseExcHelper(TypeError, "exceptions must be old-style classes or derived from BaseException, not %s", getTypeName(arg0)->c_str()); }
void raise3(Box* arg0, Box* arg1, Box* arg2) { RELEASE_ASSERT(arg2 == None, "unsupported"); if (isSubclass(arg0->cls, type_cls)) { BoxedClass* c = static_cast<BoxedClass*>(arg0); if (isSubclass(c, Exception)) { Box* exc_obj; if (arg1 != None) exc_obj = exceptionNew2(c, arg1); else exc_obj = exceptionNew1(c); raiseExc(exc_obj); } else { raiseExcHelper(TypeError, "exceptions must be old-style classes or derived from BaseException, not %s", getTypeName(arg0)->c_str()); } } if (arg1 != None) raiseExcHelper(TypeError, "instance exception may not have a separate value"); // TODO: should only allow throwing of old-style classes or things derived // from BaseException: raiseExc(arg0); }
Box* complexNew(Box* _cls, Box* real, Box* imag) { RELEASE_ASSERT(_cls == complex_cls, ""); double real_f; if (isSubclass(real->cls, int_cls)) { real_f = static_cast<BoxedInt*>(real)->n; } else if (real->cls == float_cls) { real_f = static_cast<BoxedFloat*>(real)->d; } else { // TODO: implement taking a string argument raiseExcHelper(TypeError, "complex() argument must be a string or number"); } double imag_f; if (isSubclass(imag->cls, int_cls)) { imag_f = static_cast<BoxedInt*>(imag)->n; } else if (imag->cls == float_cls) { imag_f = static_cast<BoxedFloat*>(imag)->d; } else if (imag->cls == str_cls) { raiseExcHelper(TypeError, "complex() second arg can't be a string"); } else { raiseExcHelper(TypeError, "complex() argument must be a string or number"); } return new BoxedComplex(real_f, imag_f); }
void raise3(Box* arg0, Box* arg1, Box* arg2) { // TODO switch this to PyErr_Normalize if (arg2 == None) arg2 = getTraceback(); if (isSubclass(arg0->cls, type_cls)) { BoxedClass* c = static_cast<BoxedClass*>(arg0); if (isSubclass(c, BaseException)) { Box* exc_obj; if (isSubclass(arg1->cls, BaseException)) { exc_obj = arg1; c = exc_obj->cls; } else if (arg1 != None) { exc_obj = runtimeCall(c, ArgPassSpec(1), arg1, NULL, NULL, NULL, NULL); } else { exc_obj = runtimeCall(c, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL); } raiseRaw(ExcInfo(c, exc_obj, arg2)); } } if (isSubclass(arg0->cls, BaseException)) { if (arg1 != None) raiseExcHelper(TypeError, "instance exception may not have a separate value"); raiseRaw(ExcInfo(arg0->cls, arg0, arg2)); } raiseExcHelper(TypeError, "exceptions must be old-style classes or derived from BaseException, not %s", getTypeName(arg0)); }
extern "C" Box* intTruedivInt(BoxedInt* lhs, BoxedInt* rhs) { assert(isSubclass(lhs->cls, int_cls)); assert(isSubclass(rhs->cls, int_cls)); if (rhs->n == 0) { raiseExcHelper(ZeroDivisionError, "division by zero"); } return boxFloat(lhs->n / (double)rhs->n); }
extern "C" Box* intRShiftInt(BoxedInt* lhs, BoxedInt* rhs) { assert(isSubclass(lhs->cls, int_cls)); assert(isSubclass(rhs->cls, int_cls)); if (rhs->n < 0) raiseExcHelper(ValueError, "negative shift count"); return boxInt(lhs->n >> rhs->n); }
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; }
extern "C" Box* intEq(BoxedInt* lhs, Box* rhs) { if (!isSubclass(lhs->cls, int_cls)) raiseExcHelper(TypeError, "descriptor '__eq__' requires a 'int' object but received a '%s'", getTypeName(lhs)); if (isSubclass(rhs->cls, int_cls)) { BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs); return boxBool(lhs->n == rhs_int->n); } else { return NotImplemented; } }
extern "C" Box* intDiv(BoxedInt* lhs, Box* rhs) { if (!isSubclass(lhs->cls, int_cls)) raiseExcHelper(TypeError, "descriptor '__div__' requires a 'int' object but received a '%s'", getTypeName(lhs)); if (isSubclass(rhs->cls, int_cls)) { return intDivInt(lhs, static_cast<BoxedInt*>(rhs)); } else if (rhs->cls == float_cls) { return intDivFloat(lhs, static_cast<BoxedFloat*>(rhs)); } else { return NotImplemented; } }
extern "C" Box* intAdd(BoxedInt* lhs, Box* rhs) { if (!isSubclass(lhs->cls, int_cls)) raiseExcHelper(TypeError, "descriptor '__add__' requires a 'int' object but received a '%s'", getTypeName(lhs)); if (isSubclass(rhs->cls, int_cls)) { BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs); return add_i64_i64(lhs->n, rhs_int->n); } else if (rhs->cls == float_cls) { BoxedFloat* rhs_float = static_cast<BoxedFloat*>(rhs); return boxFloat(lhs->n + rhs_float->d); } else { return NotImplemented; } }
extern "C" Box* tupleNew(Box* _cls, BoxedTuple* args, BoxedDict* kwargs) { if (!isSubclass(_cls->cls, type_cls)) raiseExcHelper(TypeError, "tuple.__new__(X): X is not a type object (%s)", getTypeName(_cls)); BoxedClass* cls = static_cast<BoxedClass*>(_cls); if (!isSubclass(cls, tuple_cls)) raiseExcHelper(TypeError, "tuple.__new__(%s): %s is not a subtype of tuple", getNameOfClass(cls), getNameOfClass(cls)); int args_sz = args->size(); int kwargs_sz = kwargs ? kwargs->d.size() : 0; if (args_sz + kwargs_sz > 1) raiseExcHelper(TypeError, "tuple() takes at most 1 argument (%d given)", args_sz + kwargs_sz); if (args_sz || kwargs_sz) { Box* elements; // if initializing from iterable argument, check common case positional args first if (args_sz) { elements = args->elts[0]; } else { assert(kwargs_sz); auto const seq = *(kwargs->d.begin()); auto const kw = static_cast<BoxedString*>(seq.first); if (kw->s() == "sequence") elements = seq.second; else raiseExcHelper(TypeError, "'%s' is an invalid keyword argument for this function", kw->data()); } if (cls == tuple_cls) { // Call PySequence_Tuple since it has some perf special-cases // that can make it quite a bit faster than the generic pyElements iteration: Box* r = PySequence_Tuple(elements); if (!r) throwCAPIException(); return r; } std::vector<Box*, StlCompatAllocator<Box*>> elts; for (auto e : elements->pyElements()) elts.push_back(e); return BoxedTuple::create(elts.size(), &elts[0], cls); } else { return BoxedTuple::create(0, cls); } }
Box* dictLen(BoxedDict* self) { if (!isSubclass(self->cls, dict_cls)) raiseExcHelper(TypeError, "descriptor '__len__' requires a 'dict' object but received a '%s'", getTypeName(self)); return boxInt(self->d.size()); }
static Box* acquire(Box* _self, Box* _waitflag) { RELEASE_ASSERT(_self->cls == thread_lock_cls, ""); BoxedThreadLock* self = static_cast<BoxedThreadLock*>(_self); RELEASE_ASSERT(isSubclass(_waitflag->cls, int_cls), ""); int waitflag = static_cast<BoxedInt*>(_waitflag)->n; // Copied + adapted from CPython: int success; auto thelock = &self->lock; int status, error = 0; { threading::GLAllowThreadsReadRegion _allow_threads; do { if (waitflag) status = fix_status(pthread_mutex_lock(thelock)); else status = fix_status(pthread_mutex_trylock(thelock)); } while (status == EINTR); /* Retry if interrupted by a signal */ } if (waitflag) { CHECK_STATUS("mutex_lock"); } else if (status != EBUSY) { CHECK_STATUS("mutex_trylock"); } success = (status == 0) ? 1 : 0; RELEASE_ASSERT(status == 0 || !waitflag, "could not lock mutex! error %d", status); return boxBool(status == 0); }
Box* setRemove(BoxedSet* self, Box* key) { RELEASE_ASSERT(isSubclass(self->cls, set_cls), ""); if (PySet_Check(key)) { try { bool existed = _setRemove(self, key); if (existed) return incref(None); } catch (ExcInfo e) { if (!e.matches(TypeError)) throw e; e.clear(); BoxedSet* tmpKey = makeNewSet(frozenset_cls, key); AUTO_DECREF(tmpKey); bool existed = _setRemove(self, tmpKey); if (existed) return incref(None); } raiseExcHelper(KeyError, key); } bool existed = _setRemove(self, key); if (existed) return incref(None); raiseExcHelper(KeyError, key); }
Box* frozensetNew(Box* _cls, Box* container, BoxedDict* kwargs) { RELEASE_ASSERT(_cls->cls == type_cls, ""); BoxedClass* cls = static_cast<BoxedClass*>(_cls); RELEASE_ASSERT(isSubclass(cls, frozenset_cls), ""); if (_cls == frozenset_cls && !_PyArg_NoKeywords("frozenset()", kwargs)) { throwCAPIException(); } if (_cls != frozenset_cls) { return makeNewSet(cls, container); } if (container != NULL) { if (container->cls == frozenset_cls) return incref(container); BoxedSet* result = makeNewSet(cls, container); if (result->s.size() != 0) { return result; } Py_DECREF(result); } static Box* emptyfrozenset = NULL; if (!emptyfrozenset) { emptyfrozenset = new (frozenset_cls) BoxedSet(); PyGC_RegisterStaticConstant(emptyfrozenset); } Py_INCREF(emptyfrozenset); return emptyfrozenset; }
static Box* propertyInit(Box* _self, Box* fget, Box* fset, Box** args) { RELEASE_ASSERT(isSubclass(_self->cls, property_cls), ""); Box* fdel = args[0]; Box* doc = args[1]; BoxedProperty* self = static_cast<BoxedProperty*>(_self); Box* prev_get = self->prop_get; Box* prev_set = self->prop_set; Box* prev_del = self->prop_del; Box* prev_doc = self->prop_doc; self->prop_get = fget == Py_None ? NULL : incref(fget); self->prop_set = fset == Py_None ? NULL : incref(fset); self->prop_del = fdel == Py_None ? NULL : incref(fdel); self->prop_doc = xincref(doc); self->getter_doc = false; Py_XDECREF(prev_get); Py_XDECREF(prev_set); Py_XDECREF(prev_del); Py_XDECREF(prev_doc); /* if no docstring given and the getter has one, use that one */ if ((doc == NULL || doc == Py_None) && fget != NULL) { propertyDocCopy(self, fget); } return incref(Py_None); }
static Box* property_copy(BoxedProperty* old, Box* get, Box* set, Box* del) { RELEASE_ASSERT(isSubclass(old->cls, property_cls), ""); if (!get || get == Py_None) get = old->prop_get; if (!set || set == Py_None) set = old->prop_set; if (!del || del == Py_None) del = old->prop_del; // Optimization for the case when the old propery is not subclassed if (old->cls == property_cls) { BoxedProperty* prop = new BoxedProperty(get, set, del, old->prop_doc); prop->getter_doc = false; if ((old->getter_doc && get != Py_None) || !old->prop_doc) propertyDocCopy(prop, get); return prop; } else { if (!get) get = Py_None; if (!set) set = Py_None; if (!del) del = Py_None; Box* doc; if ((old->getter_doc && get != Py_None) || !old->prop_doc) doc = Py_None; else doc = old->prop_doc; return runtimeCall(old->cls, ArgPassSpec(4), get, set, del, &doc, NULL); } }
Box* dictClear(BoxedDict* self) { if (!isSubclass(self->cls, dict_cls)) raiseExcHelper(TypeError, "descriptor 'clear' requires a 'dict' object but received a '%s'", getTypeName(self)); self->d.clear(); return None; }
// Ported from the CPython version: BoxedClass* supercheck(BoxedClass* type, Box* obj) { if (isSubclass(obj->cls, type_cls) && isSubclass(static_cast<BoxedClass*>(obj), type)) return static_cast<BoxedClass*>(obj); if (isSubclass(obj->cls, type)) { return obj->cls; } Box* class_attr = obj->getattr(class_str); if (class_attr && isSubclass(class_attr->cls, type_cls) && class_attr != obj->cls) { Py_FatalError("warning: this path never tested"); // blindly copied from CPython return static_cast<BoxedClass*>(class_attr); } raiseExcHelper(TypeError, "super(type, obj): obj must be an instance or subtype of type"); }
extern "C" Box* intInvert(BoxedInt* v) { if (!isSubclass(v->cls, int_cls)) raiseExcHelper(TypeError, "descriptor '__invert__' requires a 'int' object but received a '%s'", getTypeName(v)); return boxInt(~v->n); }
extern "C" Box* intTrunc(BoxedInt* self) { if (!isSubclass(self->cls, int_cls)) raiseExcHelper(TypeError, "descriptor '__trunc__' requires a 'int' object but received a '%s'", getTypeName(self)); return self; }
extern "C" Box* intNonzero(BoxedInt* v) { if (!isSubclass(v->cls, int_cls)) raiseExcHelper(TypeError, "descriptor '__nonzero__' requires a 'int' object but received a '%s'", getTypeName(v)); return boxBool(v->n != 0); }
Box* BoxedMethodDescriptor::__call__(BoxedMethodDescriptor* self, Box* obj, BoxedTuple* varargs, Box** _args) { STAT_TIMER(t0, "us_timer_boxedmethoddescriptor__call__", 10); BoxedDict* kwargs = static_cast<BoxedDict*>(_args[0]); assert(self->cls == method_cls); assert(varargs->cls == tuple_cls); assert(kwargs->cls == dict_cls); int ml_flags = self->method->ml_flags; int call_flags; if (ml_flags & METH_CLASS) { if (!isSubclass(obj->cls, type_cls)) raiseExcHelper(TypeError, "descriptor '%s' requires a type but received a '%s'", self->method->ml_name, getFullTypeName(obj).c_str()); call_flags = ml_flags & (~METH_CLASS); } else { if (!isSubclass(obj->cls, self->type)) raiseExcHelper(TypeError, "descriptor '%s' requires a '%s' object but received a '%s'", self->method->ml_name, getFullNameOfClass(self->type).c_str(), getFullTypeName(obj).c_str()); call_flags = ml_flags; } threading::GLPromoteRegion _gil_lock; Box* rtn; if (call_flags == METH_NOARGS) { RELEASE_ASSERT(varargs->size() == 0, ""); RELEASE_ASSERT(kwargs->d.size() == 0, ""); rtn = (Box*)self->method->ml_meth(obj, NULL); } else if (call_flags == METH_VARARGS) { RELEASE_ASSERT(kwargs->d.size() == 0, ""); rtn = (Box*)self->method->ml_meth(obj, varargs); } else if (call_flags == (METH_VARARGS | METH_KEYWORDS)) { rtn = (Box*)((PyCFunctionWithKeywords)self->method->ml_meth)(obj, varargs, kwargs); } else if (call_flags == METH_O) { RELEASE_ASSERT(kwargs->d.size() == 0, ""); RELEASE_ASSERT(varargs->size() == 1, ""); rtn = (Box*)self->method->ml_meth(obj, varargs->elts[0]); } else { RELEASE_ASSERT(0, "0x%x", call_flags); } checkAndThrowCAPIException(); assert(rtn && "should have set + thrown an exception!"); return rtn; }
Box* dictViewItems(BoxedDict* self) { if (!isSubclass(self->cls, dict_cls)) { raiseExcHelper(TypeError, "descriptor 'viewitems' requires a 'dict' object but received a '%s'", getTypeName(self)); } BoxedDictView* rtn = new (dict_items_cls) BoxedDictView(self); return rtn; }
Box* dictCopy(BoxedDict* self) { if (!isSubclass(self->cls, dict_cls)) raiseExcHelper(TypeError, "descriptor 'copy' requires a 'dict' object but received a '%s'", getTypeName(self)); BoxedDict* r = new BoxedDict(); r->d.insert(self->d.begin(), self->d.end()); return r; }
extern "C" BoxedString* intRepr(BoxedInt* v) { if (!isSubclass(v->cls, int_cls)) raiseExcHelper(TypeError, "descriptor '__repr__' requires a 'int' object but received a '%s'", getTypeName(v)); char buf[80]; int len = snprintf(buf, 80, "%ld", v->n); return static_cast<BoxedString*>(boxString(llvm::StringRef(buf, len))); }
extern "C" Box* intPos(BoxedInt* v) { if (!isSubclass(v->cls, int_cls)) raiseExcHelper(TypeError, "descriptor '__pos__' requires a 'int' object but received a '%s'", getTypeName(v)); if (v->cls == int_cls) return v; return boxInt(v->n); }
extern "C" Box* complexDivInt(BoxedComplex* lhs, BoxedInt* rhs) { assert(lhs->cls == complex_cls); assert(isSubclass(rhs->cls, int_cls)); if (rhs->n == 0) { raiseDivZeroExc(); } return boxComplex(lhs->real / (double)rhs->n, lhs->imag / (double)rhs->n); }
static Box* staticmethodInit(Box* _self, Box* f) { RELEASE_ASSERT(isSubclass(_self->cls, staticmethod_cls), ""); BoxedStaticmethod* self = static_cast<BoxedStaticmethod*>(_self); Py_CLEAR(self->sm_callable); self->sm_callable = incref(f); return incref(Py_None); }
Box* tupleGetitemSlice(BoxedTuple* self, BoxedSlice* slice) { assert(isSubclass(self->cls, tuple_cls)); assert(slice->cls == slice_cls); i64 start, stop, step, length; parseSlice(slice, self->size(), &start, &stop, &step, &length); return _tupleSlice(self, start, stop, step, length); }