Skip to content

Subclassing the bool from long instead int object. #1424

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: py3
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@ addons:
- kubuntu-backports
- llvm-toolchain-precise-3.5
- ubuntu-toolchain-r-test
- george-edison55-precise-backports
packages:
- autoconf
- ccache
- clang-3.5
- cmake
- cmake-data
- g++-4.8
- gdb
- gfortran
Expand Down
4 changes: 1 addition & 3 deletions from_cpython/Include/boolobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ extern "C" {
#endif


typedef PyIntObject PyBoolObject;

// Pyston change: this is no longer a static object
PyAPI_DATA(PyTypeObject*) bool_cls;
#define PyBool_Type (*bool_cls)
Expand All @@ -22,7 +20,7 @@ Don't forget to apply Py_INCREF() when returning either!!! */

// Pyston change: these are currently stored as pointers, not as static globals
/* Don't use these directly */
//PyAPI_DATA(PyIntObject) _Py_ZeroStruct, _Py_TrueStruct;
// PyAPI_DATA(struct _longobject) _Py_FalseStruct, _Py_TrueStruct;
PyAPI_DATA(PyObject) *pyston_True, *pyston_False;
/* Use these macros */
#define Py_False ((PyObject *) pyston_False)
Expand Down
10 changes: 8 additions & 2 deletions from_cpython/Modules/_sre.c
Original file line number Diff line number Diff line change
Expand Up @@ -3310,9 +3310,15 @@ static Py_ssize_t
match_getindex(MatchObject* self, PyObject* index)
{
Py_ssize_t i;

// py3update, bool become long object, temporary fixing.
if (index == NULL)
/* Default value */
return 0;

if (PyInt_Check(index))
return PyInt_AsSsize_t(index);
if (PyIndex_Check(index)) {
return PyNumber_AsSsize_t(index, NULL);
}

i = -1;

Expand Down
16 changes: 8 additions & 8 deletions src/runtime/bool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

#include "core/common.h"
#include "core/types.h"
#include "runtime/int.h"
#include "runtime/long.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"

Expand Down Expand Up @@ -62,19 +62,19 @@ extern "C" Box* boolAnd(BoxedBool* lhs, BoxedBool* rhs) {
getTypeName(lhs));

if (!PyBool_Check(rhs))
return intAnd(lhs, rhs);
return longAnd(lhs, rhs);

return boxBool(lhs->n && rhs->n);
return boxBool((lhs == Py_True) & (rhs == Py_True));
}

extern "C" Box* boolOr(BoxedBool* lhs, BoxedBool* rhs) {
if (!PyBool_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__or__' requires a 'bool' object but received a '%s'", getTypeName(lhs));

if (!PyBool_Check(rhs))
return intOr(lhs, rhs);
return longOr(lhs, rhs);

return boxBool(lhs->n || rhs->n);
return boxBool((lhs == Py_True) | (rhs == Py_True));
}

extern "C" Box* boolXor(BoxedBool* lhs, BoxedBool* rhs) {
Expand All @@ -83,9 +83,9 @@ extern "C" Box* boolXor(BoxedBool* lhs, BoxedBool* rhs) {
getTypeName(lhs));

if (!PyBool_Check(rhs))
return intXor(lhs, rhs);
return longXor(lhs, rhs);

return boxBool(lhs->n ^ rhs->n);
return boxBool((lhs == Py_True) ^ (rhs == Py_True));
}


Expand All @@ -111,6 +111,6 @@ void setupBool() {
bool_cls->freeze();
bool_cls->tp_hash = (hashfunc)bool_hash;
bool_cls->tp_repr = boolRepr<CAPI>;
bool_as_number.nb_int = int_cls->tp_as_number->nb_int;
bool_as_number.nb_int = long_cls->tp_as_number->nb_int;
}
}
2 changes: 1 addition & 1 deletion src/runtime/builtin_modules/pyston.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ static Box* dumpStats(Box* includeZeros) {
if (includeZeros->cls != bool_cls)
raiseExcHelper(TypeError, "includeZeros must be a 'bool' object but received a '%s'",
getTypeName(includeZeros));
Stats::dump(((BoxedBool*)includeZeros)->n != 0);
Stats::dump(((BoxedBool*)includeZeros) != Py_False);
Py_RETURN_NONE;
}

Expand Down
26 changes: 14 additions & 12 deletions src/runtime/long.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -777,19 +777,20 @@ template <ExceptionStyle S> Box* longNew(Box* _cls, Box* val, Box* base) noexcep
return rtn;
}

static Box* long_int(Box* v) noexcept {
int overflow = 0;
long n = PyLong_AsLongAndOverflow(v, &overflow);
static_assert(sizeof(BoxedInt::n) == sizeof(long), "");
BoxedLong* rtn = new BoxedLong();
mpz_init_set(rtn->n, ((BoxedLong*)v)->n);
return rtn;
}

Box* longInt(Box* v) {
if (!PyLong_Check(v))
raiseExcHelper(TypeError, "descriptor '__int__' requires a 'long' object but received a '%s'", getTypeName(v));

int overflow = 0;
long n = PyLong_AsLongAndOverflow(v, &overflow);
static_assert(sizeof(BoxedInt::n) == sizeof(long), "");
if (overflow) {
BoxedLong* rtn = new BoxedLong();
mpz_init_set(rtn->n, ((BoxedLong*)v)->n);
return rtn;
} else
return boxInt(n);
return long_int(v);
}

Box* longToLong(Box* self) noexcept {
Expand Down Expand Up @@ -949,7 +950,7 @@ Box* longAdd(BoxedLong* v1, Box* _v2) {
}

// TODO: split common code out into a helper function
extern "C" Box* longAnd(BoxedLong* v1, Box* _v2) {
Box* longAnd(BoxedLong* v1, Box* _v2) {
if (!PyLong_Check(v1))
raiseExcHelper(TypeError, "descriptor '__and__' requires a 'long' object but received a '%s'", getTypeName(v1));
if (PyLong_Check(_v2)) {
Expand All @@ -975,7 +976,7 @@ extern "C" Box* longAnd(BoxedLong* v1, Box* _v2) {
return incref(NotImplemented);
}

extern "C" Box* longOr(BoxedLong* v1, Box* _v2) {
Box* longOr(BoxedLong* v1, Box* _v2) {
if (!PyLong_Check(v1))
raiseExcHelper(TypeError, "descriptor '__or__' requires a 'long' object but received a '%s'", getTypeName(v1));
if (PyLong_Check(_v2)) {
Expand All @@ -1001,7 +1002,7 @@ extern "C" Box* longOr(BoxedLong* v1, Box* _v2) {
return incref(NotImplemented);
}

extern "C" Box* longXor(BoxedLong* v1, Box* _v2) {
Box* longXor(BoxedLong* v1, Box* _v2) {
if (!PyLong_Check(v1))
raiseExcHelper(TypeError, "descriptor '__xor__' requires a 'long' object but received a '%s'", getTypeName(v1));
if (PyLong_Check(_v2)) {
Expand Down Expand Up @@ -1811,6 +1812,7 @@ void setupLong() {
long_cls->freeze();

long_cls->tp_as_number->nb_power = long_pow;
long_cls->tp_as_number->nb_int = long_int;
long_cls->tp_hash = long_hash;
long_cls->tp_repr = longRepr<CAPI>;
long_cls->tp_str = longStr<CAPI>;
Expand Down
15 changes: 3 additions & 12 deletions src/runtime/long.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
#define PYSTON_RUNTIME_LONG_H

#include <cstddef>
#include <gmp.h>

#include "core/types.h"
#include "runtime/types.h"
Expand All @@ -27,23 +26,15 @@ void setupLong();

extern BoxedClass* long_cls;

class BoxedLong : public Box {
public:
mpz_t n;

BoxedLong() __attribute__((visibility("default"))) {}

static void tp_dealloc(Box* b) noexcept;

DEFAULT_CLASS_SIMPLE(long_cls, false);
};

extern "C" Box* createLong(llvm::StringRef s);
extern "C" BoxedLong* boxLong(int64_t n);

Box* longNeg(BoxedLong* lhs);
Box* longAbs(BoxedLong* v1);

Box* longAnd(BoxedLong* lhs, Box* rhs);
Box* longOr(BoxedLong* lhs, Box* rhs);
Box* longXor(BoxedLong* lhs, Box* rhs);
Box* longAdd(BoxedLong* lhs, Box* rhs);
Box* longSub(BoxedLong* lhs, Box* rhs);
Box* longMul(BoxedLong* lhs, Box* rhs);
Expand Down
10 changes: 2 additions & 8 deletions src/runtime/objmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3255,7 +3255,7 @@ static bool nonzeroHelper(STOLEN(Box*) r) {
// I believe this behavior is handled by the slot wrappers in CPython:
if (r->cls == bool_cls) {
BoxedBool* b = static_cast<BoxedBool*>(r);
bool rtn = b->n;
bool rtn = (b == Py_True);
return rtn;
} else if (r->cls == int_cls) {
BoxedInt* b = static_cast<BoxedInt*>(r);
Expand Down Expand Up @@ -3285,14 +3285,8 @@ extern "C" bool nonzero(Box* obj) {
// able to at least generate rewrites that are as good as the ones we write here.
// But for now we can't and these should be a bit faster:
if (obj->cls == bool_cls) {
// TODO: is it faster to compare to True? (especially since it will be a constant we can embed in the rewrite)
if (rewriter.get()) {
RewriterVar* b = r_obj->getAttr(offsetof(BoxedBool, n), rewriter->getReturnDestination());
rewriter->commitReturningNonPython(b);
}

BoxedBool* bool_obj = static_cast<BoxedBool*>(obj);
return bool_obj->n;
return bool_obj == Py_True;
} else if (obj->cls == int_cls) {
if (rewriter.get()) {
RewriterVar* n = r_obj->getAttr(offsetof(BoxedInt, n), rewriter->getReturnDestination());
Expand Down
10 changes: 5 additions & 5 deletions src/runtime/types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4262,11 +4262,11 @@ void setupRuntime() {
int_cls = new (0) BoxedClass(object_cls, 0, 0, sizeof(BoxedInt), false, "int", true, BoxedInt::tp_dealloc,
/*BoxedInt::tp_free*/ NULL, false);
int_cls->tp_flags |= Py_TPFLAGS_INT_SUBCLASS;
bool_cls = new (0) BoxedClass(int_cls, 0, 0, sizeof(BoxedBool), false, "bool", false, NULL, NULL, false);
complex_cls = new (0) BoxedClass(object_cls, 0, 0, sizeof(BoxedComplex), false, "complex", true, NULL, NULL, false);
long_cls = new (0)
BoxedClass(object_cls, 0, 0, sizeof(BoxedLong), false, "long", true, BoxedLong::tp_dealloc, NULL, false);
long_cls->tp_flags |= Py_TPFLAGS_LONG_SUBCLASS;
bool_cls = new (0) BoxedClass(long_cls, 0, 0, sizeof(BoxedLong), false, "bool", false, NULL, NULL, false);
float_cls = new (0)
BoxedClass(object_cls, 0, 0, sizeof(BoxedFloat), false, "float", true, BoxedFloat::tp_dealloc, NULL, false);
function_cls = new (0) BoxedClass(object_cls, offsetof(BoxedFunction, attrs), offsetof(BoxedFunction, weakreflist),
Expand Down Expand Up @@ -4304,9 +4304,9 @@ void setupRuntime() {
attrwrapper_cls->tp_mro = BoxedTuple::create({ attrwrapper_cls, object_cls });
dict_cls->tp_mro = BoxedTuple::create({ dict_cls, object_cls });
int_cls->tp_mro = BoxedTuple::create({ int_cls, object_cls });
bool_cls->tp_mro = BoxedTuple::create({ bool_cls, int_cls, object_cls });
complex_cls->tp_mro = BoxedTuple::create({ complex_cls, object_cls });
long_cls->tp_mro = BoxedTuple::create({ long_cls, object_cls });
bool_cls->tp_mro = BoxedTuple::create({ bool_cls, long_cls, object_cls });
float_cls->tp_mro = BoxedTuple::create({ float_cls, object_cls });
function_cls->tp_mro = BoxedTuple::create({ function_cls, object_cls });
builtin_function_or_method_cls->tp_mro = BoxedTuple::create({ builtin_function_or_method_cls, object_cls });
Expand All @@ -4318,13 +4318,13 @@ void setupRuntime() {
STR = typeFromClass(str_cls);
BOXED_INT = typeFromClass(int_cls);
BOXED_FLOAT = typeFromClass(float_cls);
BOXED_BOOL = typeFromClass(bool_cls);
NONE = typeFromClass(none_cls);
LIST = typeFromClass(list_cls);
MODULE = typeFromClass(module_cls);
DICT = typeFromClass(dict_cls);
BOXED_TUPLE = typeFromClass(tuple_cls);
LONG = typeFromClass(long_cls);
BOXED_BOOL = typeFromClass(bool_cls);
BOXED_COMPLEX = typeFromClass(complex_cls);

pyston_True = new BoxedBool(true);
Expand Down Expand Up @@ -4362,9 +4362,9 @@ void setupRuntime() {
attrwrapper_cls->finishInitialization();
dict_cls->finishInitialization();
int_cls->finishInitialization();
bool_cls->finishInitialization();
complex_cls->finishInitialization();
long_cls->finishInitialization();
bool_cls->finishInitialization();
float_cls->finishInitialization();
function_cls->finishInitialization();
builtin_function_or_method_cls->finishInitialization();
Expand Down Expand Up @@ -4495,8 +4495,8 @@ void setupRuntime() {
assert(object_cls->tp_new == object_new);
assert(object_cls->tp_str == object_str);

setupBool();
setupLong();
setupBool();
setupFloat();
setupComplex();
setupStr();
Expand Down
17 changes: 15 additions & 2 deletions src/runtime/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#ifndef PYSTON_RUNTIME_TYPES_H
#define PYSTON_RUNTIME_TYPES_H

#include <gmp.h>
#include <llvm/ADT/StringMap.h>
#include <llvm/ADT/Twine.h>
#include <ucontext.h>
Expand Down Expand Up @@ -541,6 +542,18 @@ class BoxedInt : public Box {
static_assert(sizeof(BoxedInt) == sizeof(PyIntObject), "");
static_assert(offsetof(BoxedInt, n) == offsetof(PyIntObject, ob_ival), "");

class BoxedLong : public Box {
public:
mpz_t n;

BoxedLong() __attribute__((visibility("default"))){};
BoxedLong(int64_t ival) __attribute__((visibility("default"))) { mpz_init_set_si(n, ival); }

static void tp_dealloc(Box* b) noexcept;

DEFAULT_CLASS_SIMPLE(long_cls, false);
};

extern "C" int PyFloat_ClearFreeList() noexcept;
class BoxedFloat : public Box {
private:
Expand Down Expand Up @@ -593,9 +606,9 @@ static_assert(sizeof(BoxedComplex) == sizeof(PyComplexObject), "");
static_assert(offsetof(BoxedComplex, real) == offsetof(PyComplexObject, cval.real), "");
static_assert(offsetof(BoxedComplex, imag) == offsetof(PyComplexObject, cval.imag), "");

class BoxedBool : public BoxedInt {
class BoxedBool : public BoxedLong {
public:
BoxedBool(bool b) __attribute__((visibility("default"))) : BoxedInt(b ? 1 : 0) {}
BoxedBool(bool b) __attribute__((visibility("default"))) { mpz_init_set_si(n, b ? 1 : 0); }

DEFAULT_CLASS_SIMPLE(bool_cls, false);
};
Expand Down
6 changes: 6 additions & 0 deletions test/tests/bool_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# expected: fail

long_ = type(31415926535897932384626)
assert isinstance(True, long_)
assert issubclass(bool, long_)
print(bool.__bases__)
5 changes: 4 additions & 1 deletion tools/tester.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ def run_test(fn, check_stats, run_memcheck):
opts = get_test_options(fn, check_stats, run_memcheck)
del check_stats, run_memcheck

if opts.expected != "py3ready":
opts.skip = True

if opts.skip:
return ("(skipped: %s)" % opts.skip) if DISPLAY_SKIPS else ""

Expand Down Expand Up @@ -224,7 +227,7 @@ def get_test_options(fn, check_stats, run_memcheck):
elif os.path.basename(fn).split('.')[0] in TESTS_TO_SKIP:
opts.skip = 'command line option'

assert opts.expected in ("success", "fail", "statfail"), opts.expected
assert opts.expected in ("success", "fail", "statfail", "py3ready"), opts.expected

if TEST_PYPY:
opts.jit_args = []
Expand Down