Commit d3abbf16 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Some long support, trying to add tp_as_buffer

parent f44f2eff
......@@ -433,12 +433,9 @@ extern "C" int PyErr_ExceptionMatches(PyObject* exc) {
}
extern "C" PyObject* PyErr_Occurred() {
Py_FatalError("unimplemented");
/*
printf("need to hook exception handling -- make sure errors dont propagate into C code, and error codes get "
"checked coming out\n");
// While there clearly needs to be more here, I think this is ok for now because all of the exception-setting
// functions will abort()
return NULL;
*/
}
extern "C" int PyErr_WarnEx(PyObject* category, const char* text, Py_ssize_t stacklevel) {
......
......@@ -134,15 +134,26 @@ Box* longAdd(BoxedLong* v1, Box* _v2) {
raiseExcHelper(TypeError, "descriptor '__add__' requires a 'long' object but received a '%s'",
getTypeName(v1)->c_str());
if (!isSubclass(_v2->cls, long_cls))
return NotImplemented;
if (isSubclass(_v2->cls, long_cls)) {
BoxedLong* v2 = static_cast<BoxedLong*>(_v2);
BoxedLong* v2 = static_cast<BoxedLong*>(_v2);
BoxedLong* r = new BoxedLong(long_cls);
mpz_init(r->n);
mpz_add(r->n, v1->n, v2->n);
return r;
} else if (isSubclass(_v2->cls, int_cls)) {
BoxedInt* v2 = static_cast<BoxedInt*>(_v2);
BoxedLong* r = new BoxedLong(long_cls);
mpz_init(r->n);
mpz_add(r->n, v1->n, v2->n);
return r;
BoxedLong* r = new BoxedLong(long_cls);
mpz_init(r->n);
if (v2->n >= 0)
mpz_add_ui(r->n, v1->n, v2->n);
else
mpz_sub_ui(r->n, v1->n, -v2->n);
return r;
} else {
return NotImplemented;
}
}
Box* longSub(BoxedLong* v1, Box* _v2) {
......@@ -172,20 +183,36 @@ Box* longSub(BoxedLong* v1, Box* _v2) {
}
}
Box* longRsub(BoxedLong* v1, Box* _v2) {
if (!isSubclass(v1->cls, long_cls))
raiseExcHelper(TypeError, "descriptor '__rsub__' requires a 'long' object but received a '%s'",
getTypeName(v1)->c_str());
return longAdd(static_cast<BoxedLong*>(longNeg(v1)), _v2);
}
Box* longMul(BoxedLong* v1, Box* _v2) {
if (!isSubclass(v1->cls, long_cls))
raiseExcHelper(TypeError, "descriptor '__mul__' requires a 'long' object but received a '%s'",
getTypeName(v1)->c_str());
if (!isSubclass(_v2->cls, long_cls))
return NotImplemented;
if (isSubclass(_v2->cls, long_cls)) {
BoxedLong* v2 = static_cast<BoxedLong*>(_v2);
BoxedLong* v2 = static_cast<BoxedLong*>(_v2);
BoxedLong* r = new BoxedLong(long_cls);
mpz_init(r->n);
mpz_mul(r->n, v1->n, v2->n);
return r;
} else if (isSubclass(_v2->cls, int_cls)) {
BoxedInt* v2 = static_cast<BoxedInt*>(_v2);
BoxedLong* r = new BoxedLong(long_cls);
mpz_init(r->n);
mpz_mul(r->n, v1->n, v2->n);
return r;
BoxedLong* r = new BoxedLong(long_cls);
mpz_init(r->n);
mpz_mul_si(r->n, v1->n, v2->n);
return r;
} else {
return NotImplemented;
}
}
Box* longDiv(BoxedLong* v1, Box* _v2) {
......@@ -193,19 +220,56 @@ Box* longDiv(BoxedLong* v1, Box* _v2) {
raiseExcHelper(TypeError, "descriptor '__div__' requires a 'long' object but received a '%s'",
getTypeName(v1)->c_str());
if (!isSubclass(_v2->cls, long_cls))
if (isSubclass(_v2->cls, long_cls)) {
BoxedLong* v2 = static_cast<BoxedLong*>(_v2);
if (mpz_cmp_si(v2->n, 0) == 0)
raiseExcHelper(ZeroDivisionError, "long division or modulo by zero");
BoxedLong* r = new BoxedLong(long_cls);
mpz_init(r->n);
mpz_fdiv_q(r->n, v1->n, v2->n);
return r;
} else if (isSubclass(_v2->cls, int_cls)) {
BoxedInt* v2 = static_cast<BoxedInt*>(_v2);
if (v2->n == 0)
raiseExcHelper(ZeroDivisionError, "long division or modulo by zero");
BoxedLong* r = new BoxedLong(long_cls);
mpz_init_set_si(r->n, v2->n);
mpz_fdiv_q(r->n, v1->n, r->n);
return r;
} else {
return NotImplemented;
}
}
BoxedLong* v2 = static_cast<BoxedLong*>(_v2);
Box* longRdiv(BoxedLong* v1, Box* _v2) {
if (!isSubclass(v1->cls, long_cls))
raiseExcHelper(TypeError, "descriptor '__div__' requires a 'long' object but received a '%s'",
getTypeName(v1)->c_str());
if (mpz_cmp_si(v2->n, 0) == 0)
if (mpz_cmp_si(v1->n, 0) == 0)
raiseExcHelper(ZeroDivisionError, "long division or modulo by zero");
BoxedLong* r = new BoxedLong(long_cls);
mpz_init(r->n);
// It looks like the 'f'-family of integer functions ("floor") do the Python-style rounding
mpz_fdiv_q(r->n, v1->n, v2->n);
return r;
if (isSubclass(_v2->cls, long_cls)) {
BoxedLong* v2 = static_cast<BoxedLong*>(_v2);
BoxedLong* r = new BoxedLong(long_cls);
mpz_init(r->n);
mpz_fdiv_q(r->n, v2->n, v1->n);
return r;
} else if (isSubclass(_v2->cls, int_cls)) {
BoxedInt* v2 = static_cast<BoxedInt*>(_v2);
BoxedLong* r = new BoxedLong(long_cls);
mpz_init_set_si(r->n, v2->n);
mpz_fdiv_q(r->n, r->n, v1->n);
return r;
} else {
return NotImplemented;
}
}
Box* longPow(BoxedLong* v1, Box* _v2) {
......@@ -235,9 +299,16 @@ void setupLong() {
new BoxedFunction(boxRTFunction((void*)longNew, UNKNOWN, 2, 1, false, false), { boxInt(0) }));
long_cls->giveAttr("__mul__", new BoxedFunction(boxRTFunction((void*)longMul, UNKNOWN, 2)));
long_cls->giveAttr("__rmul__", long_cls->getattr("__mul__"));
long_cls->giveAttr("__div__", new BoxedFunction(boxRTFunction((void*)longDiv, UNKNOWN, 2)));
long_cls->giveAttr("__rdiv__", new BoxedFunction(boxRTFunction((void*)longRdiv, UNKNOWN, 2)));
long_cls->giveAttr("__sub__", new BoxedFunction(boxRTFunction((void*)longSub, UNKNOWN, 2)));
long_cls->giveAttr("__rsub__", new BoxedFunction(boxRTFunction((void*)longRsub, UNKNOWN, 2)));
long_cls->giveAttr("__add__", new BoxedFunction(boxRTFunction((void*)longAdd, UNKNOWN, 2)));
long_cls->giveAttr("__radd__", long_cls->getattr("__add__"));
long_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)longRepr, STR, 1)));
long_cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)longStr, STR, 1)));
......
......@@ -782,6 +782,33 @@ Box* strCount2(BoxedString* self, Box* elt) {
return boxInt(strCount2Unboxed(self, elt));
}
static Py_ssize_t string_buffer_getreadbuf(PyObject* self, Py_ssize_t index, const void** ptr) {
RELEASE_ASSERT(index == 0, "");
// I think maybe this can just be a non-release assert? shouldn't be able to call this with
// the wrong type
RELEASE_ASSERT(self->cls == str_cls, "");
auto s = static_cast<BoxedString*>(self);
*ptr = s->s.c_str();
return s->s.size();
}
static Py_ssize_t string_buffer_getsegcount(PyObject* o, Py_ssize_t* lenp) {
RELEASE_ASSERT(lenp == NULL, "");
RELEASE_ASSERT(o->cls == str_cls, "");
return 1;
}
static PyBufferProcs string_as_buffer = {
(readbufferproc)string_buffer_getreadbuf, // comments are the only way I've found of
(writebufferproc)NULL, // forcing clang-format to break these onto multiple lines
(segcountproc)string_buffer_getsegcount, //
(charbufferproc)NULL, //
(getbufferproc)NULL, //
(releasebufferproc)NULL,
};
void setupStr() {
str_iterator_cls = new BoxedClass(object_cls, &strIteratorGCHandler, 0, sizeof(BoxedString), false);
str_iterator_cls->giveAttr("__name__", boxStrConstant("striterator"));
......@@ -790,6 +817,8 @@ void setupStr() {
str_iterator_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)BoxedStringIterator::next, STR, 1)));
str_iterator_cls->freeze();
str_cls->tp_as_buffer = &string_as_buffer;
str_cls->giveAttr("__name__", boxStrConstant("str"));
str_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)strLen, BOXED_INT, 1)));
......
......@@ -7,10 +7,24 @@ for i in xrange(150):
t *= l
print t, repr(t)
def test(a, b):
print a, b
print a + b, b + a, a.__add__(b), b.__add__(a)
print a - b, b - a, a.__sub__(b), b.__sub__(a)
print a * b, b * a, a.__mul__(b), b.__mul__(a)
print a / b, b / a, a.__div__(b), b.__div__(a)
print 1L / 5L
print -1L / 5L
print 1L / -5L
print -1L / -5L
print (2L).__sub__(1)
print (2L).__sub__(-1)
for a in [-5, -1, 1, 5, -2L, -1L, 1L, 2L]:
for b in [-5, -1, 1, 5, -2L, -1L, 1L, 2L]:
test(a, b)
print (2L).__rdiv__(-1)
print (2L).__rdiv__(-1L)
print (-2L).__rdiv__(1L)
print (-2L).__rdiv__(1)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment