Commit 76210a33 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge branch 'int_new'

parents 8460bae3 50f1ab68
......@@ -115,10 +115,38 @@ extern "C" Box* abs_(Box* x) {
} else if (x->cls == long_cls) {
return longAbs(static_cast<BoxedLong*>(x));
} else {
RELEASE_ASSERT(0, "%s", getTypeName(x)->c_str());
static const std::string abs_str("__abs__");
return callattr(x, &abs_str, CallattrFlags({.cls_only = true, .null_on_nonexistent = false }), ArgPassSpec(0),
NULL, NULL, NULL, NULL, NULL);
}
}
extern "C" Box* hexFunc(Box* x) {
static const std::string hex_str("__hex__");
Box* r = callattr(x, &hex_str, CallattrFlags({.cls_only = true, .null_on_nonexistent = true }), ArgPassSpec(0),
NULL, NULL, NULL, NULL, NULL);
if (!r)
raiseExcHelper(TypeError, "hex() argument can't be converted to hex");
if (!isSubclass(r->cls, str_cls))
raiseExcHelper(TypeError, "__hex__() returned non-string (type %.200s)", r->cls->tp_name);
return r;
}
extern "C" Box* octFunc(Box* x) {
static const std::string oct_str("__oct__");
Box* r = callattr(x, &oct_str, CallattrFlags({.cls_only = true, .null_on_nonexistent = true }), ArgPassSpec(0),
NULL, NULL, NULL, NULL, NULL);
if (!r)
raiseExcHelper(TypeError, "oct() argument can't be converted to oct");
if (!isSubclass(r->cls, str_cls))
raiseExcHelper(TypeError, "__oct__() returned non-string (type %.200s)", r->cls->tp_name);
return r;
}
extern "C" Box* all(Box* container) {
for (Box* e : container->pyElements()) {
if (!nonzero(e)) {
......@@ -944,6 +972,8 @@ void setupBuiltins() {
builtins_module->giveAttr("hash", hash_obj);
abs_obj = new BoxedFunction(boxRTFunction((void*)abs_, UNKNOWN, 1));
builtins_module->giveAttr("abs", abs_obj);
builtins_module->giveAttr("hex", new BoxedFunction(boxRTFunction((void*)hexFunc, UNKNOWN, 1)));
builtins_module->giveAttr("oct", new BoxedFunction(boxRTFunction((void*)octFunc, UNKNOWN, 1)));
min_obj = new BoxedFunction(boxRTFunction((void*)min, UNKNOWN, 1, 0, true, false));
builtins_module->giveAttr("min", min_obj);
......
......@@ -544,31 +544,72 @@ std::string floatFmt(double x, int precision, char code) {
return std::string(buf, n);
}
Box* floatNew(BoxedClass* cls, Box* a) {
RELEASE_ASSERT(cls == float_cls, "");
BoxedFloat* _floatNew(Box* a) {
if (a->cls == float_cls) {
return a;
return static_cast<BoxedFloat*>(a);
} else if (isSubclass(a->cls, float_cls)) {
return new BoxedFloat(float_cls, static_cast<BoxedFloat*>(a)->d);
} else if (isSubclass(a->cls, int_cls)) {
return boxFloat(static_cast<BoxedInt*>(a)->n);
return new BoxedFloat(float_cls, static_cast<BoxedInt*>(a)->n);
} else if (a->cls == str_cls) {
const std::string& s = static_cast<BoxedString*>(a)->s;
if (s == "nan")
return boxFloat(NAN);
return new BoxedFloat(float_cls, NAN);
if (s == "-nan")
return boxFloat(-NAN);
return new BoxedFloat(float_cls, -NAN);
if (s == "inf")
return boxFloat(INFINITY);
return new BoxedFloat(float_cls, INFINITY);
if (s == "-inf")
return boxFloat(-INFINITY);
return new BoxedFloat(float_cls, -INFINITY);
return new BoxedFloat(float_cls, strtod(s.c_str(), NULL));
} else {
static const std::string float_str("__float__");
Box* r = callattr(a, &float_str, CallattrFlags({.cls_only = true, .null_on_nonexistent = true }),
ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
if (!r) {
fprintf(stderr, "TypeError: float() argument must be a string or a number, not '%s'\n",
getTypeName(a)->c_str());
raiseExcHelper(TypeError, "");
}
return boxFloat(strtod(s.c_str(), NULL));
if (!isSubclass(r->cls, float_cls)) {
raiseExcHelper(TypeError, "__float__ returned non-float (type %s)", r->cls->tp_name);
}
return static_cast<BoxedFloat*>(r);
}
RELEASE_ASSERT(0, "%s", getTypeName(a)->c_str());
}
Box* floatNew(BoxedClass* _cls, Box* a) {
if (!isSubclass(_cls->cls, type_cls))
raiseExcHelper(TypeError, "float.__new__(X): X is not a type object (%s)", getTypeName(_cls)->c_str());
BoxedClass* cls = static_cast<BoxedClass*>(_cls);
if (!isSubclass(cls, float_cls))
raiseExcHelper(TypeError, "float.__new__(%s): %s is not a subtype of float", getNameOfClass(cls)->c_str(),
getNameOfClass(cls)->c_str());
if (cls == float_cls)
return _floatNew(a);
BoxedFloat* f = _floatNew(a);
assert(cls->tp_basicsize >= sizeof(BoxedFloat));
void* mem = gc_alloc(cls->tp_basicsize, gc::GCKind::PYTHON);
BoxedFloat* rtn = ::new (mem) BoxedFloat(cls, 0);
initUserAttrs(rtn, cls);
rtn->d = f->d;
return rtn;
}
Box* floatStr(BoxedFloat* self) {
assert(self->cls == float_cls);
if (!isSubclass(self->cls, float_cls))
raiseExcHelper(TypeError, "descriptor '__str__' requires a 'float' object but received a '%s'",
getTypeName(self)->c_str());
return boxString(floatFmt(self->d, 12, 'g'));
}
......
......@@ -23,7 +23,7 @@ namespace pyston {
extern "C" inline Box* boxFloat(double d) __attribute__((visibility("default")));
extern "C" inline Box* boxFloat(double d) {
return new BoxedFloat(d);
return new BoxedFloat(float_cls, d);
}
extern "C" inline Box* boxComplex(double r, double i) __attribute__((visibility("default")));
......
......@@ -733,33 +733,42 @@ extern "C" Box* intHash(BoxedInt* self) {
return boxInt(self->n);
}
extern "C" Box* intNew(Box* _cls, Box* val) {
if (!isSubclass(_cls->cls, type_cls))
raiseExcHelper(TypeError, "int.__new__(X): X is not a type object (%s)", getTypeName(_cls)->c_str());
extern "C" Box* intHex(BoxedInt* self) {
if (!isSubclass(self->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__hex__' requires a 'int' object but received a '%s'",
getTypeName(self)->c_str());
BoxedClass* cls = static_cast<BoxedClass*>(_cls);
if (!isSubclass(cls, int_cls))
raiseExcHelper(TypeError, "int.__new__(%s): %s is not a subtype of int", getNameOfClass(cls)->c_str(),
getNameOfClass(cls)->c_str());
char buf[80];
int len = snprintf(buf, sizeof(buf), "0x%lx", self->n);
return new BoxedString(std::string(buf, len));
}
assert(cls->tp_basicsize >= sizeof(BoxedInt));
void* mem = gc_alloc(cls->tp_basicsize, gc::GCKind::PYTHON);
BoxedInt* rtn = ::new (mem) BoxedInt(cls, 0);
initUserAttrs(rtn, cls);
extern "C" Box* intOct(BoxedInt* self) {
if (!isSubclass(self->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__oct__' requires a 'int' object but received a '%s'",
getTypeName(self)->c_str());
char buf[80];
int len = snprintf(buf, sizeof(buf), "%#lo", self->n);
return new BoxedString(std::string(buf, len));
}
BoxedInt* _intNew(Box* val) {
if (isSubclass(val->cls, int_cls)) {
rtn->n = static_cast<BoxedInt*>(val)->n;
BoxedInt* n = static_cast<BoxedInt*>(val);
if (val->cls == int_cls)
return n;
return new BoxedInt(int_cls, n->n);
} else if (val->cls == str_cls) {
BoxedString* s = static_cast<BoxedString*>(val);
std::istringstream ss(s->s);
int64_t n;
ss >> n;
rtn->n = n;
return new BoxedInt(int_cls, n);
} else if (val->cls == float_cls) {
double d = static_cast<BoxedFloat*>(val)->d;
rtn->n = d;
return new BoxedInt(int_cls, d);
} else {
static const std::string int_str("__int__");
Box* r = callattr(val, &int_str, CallattrFlags({.cls_only = true, .null_on_nonexistent = true }),
......@@ -774,8 +783,30 @@ extern "C" Box* intNew(Box* _cls, Box* val) {
if (!isSubclass(r->cls, int_cls)) {
raiseExcHelper(TypeError, "__int__ returned non-int (type %s)", r->cls->tp_name);
}
rtn->n = static_cast<BoxedInt*>(r)->n;
return static_cast<BoxedInt*>(r);
}
}
extern "C" Box* intNew(Box* _cls, Box* val) {
if (!isSubclass(_cls->cls, type_cls))
raiseExcHelper(TypeError, "int.__new__(X): X is not a type object (%s)", getTypeName(_cls)->c_str());
BoxedClass* cls = static_cast<BoxedClass*>(_cls);
if (!isSubclass(cls, int_cls))
raiseExcHelper(TypeError, "int.__new__(%s): %s is not a subtype of int", getNameOfClass(cls)->c_str(),
getNameOfClass(cls)->c_str());
if (cls == int_cls)
return _intNew(val);
BoxedInt* n = _intNew(val);
assert(cls->tp_basicsize >= sizeof(BoxedInt));
void* mem = gc_alloc(cls->tp_basicsize, gc::GCKind::PYTHON);
BoxedInt* rtn = ::new (mem) BoxedInt(cls, 0);
initUserAttrs(rtn, cls);
rtn->n = n->n;
return rtn;
}
......@@ -855,6 +886,9 @@ void setupInt() {
int_cls->giveAttr("__hash__", new BoxedFunction(boxRTFunction((void*)intHash, BOXED_INT, 1)));
int_cls->giveAttr("__divmod__", new BoxedFunction(boxRTFunction((void*)intDivmod, BOXED_TUPLE, 2)));
int_cls->giveAttr("__hex__", new BoxedFunction(boxRTFunction((void*)intHex, STR, 1)));
int_cls->giveAttr("__oct__", new BoxedFunction(boxRTFunction((void*)intOct, STR, 1)));
int_cls->giveAttr("__new__",
new BoxedFunction(boxRTFunction((void*)intNew, BOXED_INT, 2, 1, false, false), { boxInt(0) }));
......
......@@ -290,20 +290,8 @@ extern "C" PyObject* PyLong_FromUnsignedLongLong(unsigned long long ival) {
return rtn;
}
extern "C" Box* longNew(Box* _cls, Box* val, Box* _base) {
if (!isSubclass(_cls->cls, type_cls))
raiseExcHelper(TypeError, "long.__new__(X): X is not a type object (%s)", getTypeName(_cls)->c_str());
BoxedClass* cls = static_cast<BoxedClass*>(_cls);
if (!isSubclass(cls, long_cls))
raiseExcHelper(TypeError, "long.__new__(%s): %s is not a subtype of long", getNameOfClass(cls)->c_str(),
getNameOfClass(cls)->c_str());
assert(cls->tp_basicsize >= sizeof(BoxedInt));
void* mem = gc_alloc(cls->tp_basicsize, gc::GCKind::PYTHON);
BoxedLong* rtn = ::new (mem) BoxedLong(cls);
initUserAttrs(rtn, cls);
BoxedLong* _longNew(Box* val, Box* _base) {
BoxedLong* rtn = new BoxedLong(long_cls);
if (_base) {
if (!isSubclass(_base->cls, int_cls))
raiseExcHelper(TypeError, "an integer is required");
......@@ -326,21 +314,64 @@ extern "C" Box* longNew(Box* _cls, Box* val, Box* _base) {
int r = mpz_init_set_str(rtn->n, s->s.c_str(), base);
RELEASE_ASSERT(r == 0, "");
} else {
if (isSubclass(val->cls, int_cls)) {
if (isSubclass(val->cls, long_cls)) {
BoxedLong* l = static_cast<BoxedLong*>(val);
if (val->cls == long_cls)
return l;
BoxedLong* rtn = new BoxedLong(long_cls);
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) {
const std::string& s = static_cast<BoxedString*>(val)->s;
int r = mpz_init_set_str(rtn->n, s.c_str(), 10);
RELEASE_ASSERT(r == 0, "");
} else {
fprintf(stderr, "TypeError: int() argument must be a string or a number, not '%s'\n",
getTypeName(val)->c_str());
raiseExcHelper(TypeError, "");
static const std::string long_str("__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)->c_str());
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);
}
}
}
return rtn;
}
extern "C" Box* longNew(Box* _cls, Box* val, Box* _base) {
if (!isSubclass(_cls->cls, type_cls))
raiseExcHelper(TypeError, "long.__new__(X): X is not a type object (%s)", getTypeName(_cls)->c_str());
BoxedClass* cls = static_cast<BoxedClass*>(_cls);
if (!isSubclass(cls, long_cls))
raiseExcHelper(TypeError, "long.__new__(%s): %s is not a subtype of long", getNameOfClass(cls)->c_str(),
getNameOfClass(cls)->c_str());
BoxedLong* l = _longNew(val, _base);
if (cls == long_cls)
return l;
assert(cls->tp_basicsize >= sizeof(BoxedInt));
void* mem = gc_alloc(cls->tp_basicsize, gc::GCKind::PYTHON);
BoxedLong* rtn = ::new (mem) BoxedLong(cls);
initUserAttrs(rtn, cls);
mpz_init_set(rtn->n, l->n);
return rtn;
}
Box* longRepr(BoxedLong* v) {
if (!isSubclass(v->cls, long_cls))
raiseExcHelper(TypeError, "descriptor '__repr__' requires a 'long' object but received a '%s'",
......
......@@ -3458,7 +3458,7 @@ Box* typeCallInternal(BoxedFunction* f, CallRewriteArgs* rewrite_args, ArgPassSp
allowable_news.push_back(object_new);
for (BoxedClass* allowed_cls : { int_cls, xrange_cls, float_cls, long_cls }) {
for (BoxedClass* allowed_cls : { xrange_cls }) {
auto new_obj = typeLookup(allowed_cls, _new_str, NULL);
gc::registerPermanentRoot(new_obj);
allowable_news.push_back(new_obj);
......@@ -3474,6 +3474,13 @@ Box* typeCallInternal(BoxedFunction* f, CallRewriteArgs* rewrite_args, ArgPassSp
}
}
if (!ok && (cls == int_cls || cls == float_cls || cls == long_cls)) {
if (npassed_args == 1)
ok = true;
else if (npassed_args == 2 && (arg2->cls == int_cls || arg2->cls == str_cls || arg2->cls == float_cls))
ok = true;
}
if (!ok) {
// Uncomment this to try to find __new__ functions that we could either white- or blacklist:
// ASSERT(cls->is_user_defined || cls == type_cls, "Does '%s' have a well-behaved __new__? if so, add to
......
......@@ -297,7 +297,7 @@ class BoxedFloat : public Box {
public:
double d;
BoxedFloat(double d) __attribute__((visibility("default"))) : Box(float_cls), d(d) {}
BoxedFloat(BoxedClass* cls, double d) __attribute__((visibility("default"))) : Box(cls), d(d) {}
};
class BoxedComplex : public Box {
......
......@@ -58,3 +58,13 @@ print vars(C()).items()
print globals().get("not a real variable")
print globals().get("not a real variable", 1)
print hex(12345)
print oct(234)
print hex(0)
print oct(0) # This should not add an additional leading 0, ie should return "0" not "00"
try:
print hex([])
except TypeError, e:
print e
......@@ -5,3 +5,34 @@ print f
print float(2)
# print f - 2
class F(float):
def __init__(self, *args):
print "F.__init__, %d args" % len(args)
f = F(1)
print f is float(f)
print type(float(f))
print float(f)
class D(object):
def __init__(self, d):
self.d = d
def __float__(self):
return self.d
for a in (1.0, D(2.0), F(), D(F())):
f = float(a)
print f, type(f)
f = float.__new__(F, a)
print f, type(f)
print type(float(D(F())))
class F2(float):
pass
print type(F2(D(F())))
print type(float(F()))
......@@ -18,7 +18,8 @@ print -1 ** 0
# Testing int.__new__:
class C(int):
pass
def __init__(self, *args):
print "C.__init__, %d args" % len(args)
class D(object):
def __init__(self, n):
......@@ -29,9 +30,20 @@ class D(object):
for a in (False, True, 2, 3.0, D(4), D(C(5)), D(False)):
i = int.__new__(C, a)
print type(i), i
print type(i), i, type(int(a))
try:
int.__new__(C, D(1.0))
except TypeError, e:
print e
class I(int):
pass
x = int(D(C()))
print type(x)
x = I(D(C()))
print type(x)
print type(int(C()))
......@@ -48,3 +48,35 @@ print long("100", 26)
print type(hash(1L))
print hash(1L) == hash(2L)
# Testing long.__new__:
class C(long):
def __init__(self, *args):
print "C.__init__, %d args" % len(args)
class D(object):
def __init__(self, n):
self.n = n
def __long__(self):
return self.n
for a in (False, True, 2, 3L, D(4), D(C(5)), D(False)):
i = long.__new__(C, a)
print type(i), i, type(long(a))
try:
long.__new__(C, D(1.0))
except TypeError, e:
print e
class I(long):
pass
x = long(D(C()))
print type(x)
x = I(D(C()))
print type(x)
print type(long(C()))
class CustomInt(int):
pass
print int.__new__(CustomInt, "1")
class CustomFloat(float):
pass
print float.__new__(CustomFloat, "1.0")
class CustomLong(long):
pass
print long.__new__(CustomLong, "10")
......@@ -80,7 +80,7 @@ def get_expected_output(fn):
if cache_mtime > os.stat(fn).st_mtime and cache_mtime > get_extmodule_mtime():
try:
return cPickle.load(open(cache_fn))
except EOFError:
except (EOFError, ValueError):
pass
# TODO don't suppress warnings globally:
......
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