Commit d544b623 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge branch 'django_dependencies'

parents a3683b3e 3ad0b5d2
...@@ -810,6 +810,9 @@ def getargspec(func): ...@@ -810,6 +810,9 @@ def getargspec(func):
'defaults' is an n-tuple of the default values of the last n arguments. 'defaults' is an n-tuple of the default values of the last n arguments.
""" """
# Pyston change:
return ArgSpec((), "args", "kw", ())
if ismethod(func): if ismethod(func):
func = func.im_func func = func.im_func
if not isfunction(func): if not isfunction(func):
......
...@@ -23,6 +23,33 @@ PyObject * _do_string_format(PyObject *self, PyObject *args, PyObject *kwargs) { ...@@ -23,6 +23,33 @@ PyObject * _do_string_format(PyObject *self, PyObject *args, PyObject *kwargs) {
return do_string_format(self, args, kwargs); return do_string_format(self, args, kwargs);
} }
PyObject * string_split(PyStringObject *self, PyObject *args)
{
Py_ssize_t len = PyString_GET_SIZE(self), n;
Py_ssize_t maxsplit = -1;
const char *s = PyString_AS_STRING(self), *sub;
PyObject *subobj = Py_None;
if (!PyArg_ParseTuple(args, "|On:split", &subobj, &maxsplit))
return NULL;
if (maxsplit < 0)
maxsplit = PY_SSIZE_T_MAX;
if (subobj == Py_None)
return stringlib_split_whitespace((PyObject*) self, s, len, maxsplit);
if (PyString_Check(subobj)) {
sub = PyString_AS_STRING(subobj);
n = PyString_GET_SIZE(subobj);
}
#ifdef Py_USING_UNICODE
else if (PyUnicode_Check(subobj))
return PyUnicode_Split((PyObject *)self, subobj, maxsplit);
#endif
else if (PyObject_AsCharBuffer(subobj, &sub, &n))
return NULL;
return stringlib_split((PyObject*) self, s, len, sub, n, maxsplit);
}
PyObject* string_rsplit(PyStringObject* self, PyObject* args) { PyObject* string_rsplit(PyStringObject* self, PyObject* args) {
Py_ssize_t len = PyString_GET_SIZE(self), n; Py_ssize_t len = PyString_GET_SIZE(self), n;
Py_ssize_t maxsplit = -1; Py_ssize_t maxsplit = -1;
......
...@@ -202,6 +202,13 @@ CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, E ...@@ -202,6 +202,13 @@ CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, E
printf("%s\n", ss.str().c_str()); printf("%s\n", ss.str().c_str());
} }
#ifndef NDEBUG
if (effort == EffortLevel::INTERPRETED) {
for (auto arg_type : spec->arg_types)
assert(arg_type == UNKNOWN);
}
#endif
// Do the analysis now if we had deferred it earlier: // Do the analysis now if we had deferred it earlier:
if (source->cfg == NULL) { if (source->cfg == NULL) {
source->cfg = computeCFG(source, source->body); source->cfg = computeCFG(source, source->body);
......
...@@ -1909,8 +1909,13 @@ public: ...@@ -1909,8 +1909,13 @@ public:
curblock->connectTo(end_block); curblock->connectTo(end_block);
} }
if (end_block->predecessors.size() == 0) {
delete end_block;
curblock = NULL;
} else {
cfg->placeBlock(end_block); cfg->placeBlock(end_block);
curblock = end_block; curblock = end_block;
}
return true; return true;
} }
...@@ -2436,8 +2441,13 @@ CFG* computeCFG(SourceInfo* source, std::vector<AST_stmt*> body) { ...@@ -2436,8 +2441,13 @@ CFG* computeCFG(SourceInfo* source, std::vector<AST_stmt*> body) {
|| terminator->type == AST_TYPE::Raise); || terminator->type == AST_TYPE::Raise);
} }
if (b->predecessors.size() == 0) if (b->predecessors.size() == 0) {
assert(b == rtn->getStartingBlock()); if (b != rtn->getStartingBlock()) {
rtn->print();
printf("%s\n", source->getName().c_str());
}
ASSERT(b == rtn->getStartingBlock(), "%d", b->idx);
}
} }
// We need to generate the CFG in a way that doesn't have any critical edges, // We need to generate the CFG in a way that doesn't have any critical edges,
......
...@@ -424,6 +424,38 @@ Box* dictFromkeys(BoxedDict* self, Box* iterable, Box* default_value) { ...@@ -424,6 +424,38 @@ Box* dictFromkeys(BoxedDict* self, Box* iterable, Box* default_value) {
return rtn; return rtn;
} }
Box* dictEq(BoxedDict* self, Box* _rhs) {
if (!isSubclass(self->cls, dict_cls))
raiseExcHelper(TypeError, "descriptor '__eq__' requires a 'dict' object but received a '%s'",
getTypeName(self));
if (!isSubclass(_rhs->cls, dict_cls))
return NotImplemented;
BoxedDict* rhs = static_cast<BoxedDict*>(_rhs);
if (self->d.size() != rhs->d.size())
return False;
for (const auto& p : self->d) {
auto it = rhs->d.find(p.first);
if (it == rhs->d.end())
return False;
if (!nonzero(compare(p.second, it->second, AST_TYPE::Eq)))
return False;
}
return True;
}
Box* dictNe(BoxedDict* self, Box* _rhs) {
Box* eq = dictEq(self, _rhs);
if (eq == NotImplemented)
return eq;
if (eq == True)
return False;
return True;
}
extern "C" Box* dictNew(Box* _cls, BoxedTuple* args, BoxedDict* kwargs) { extern "C" Box* dictNew(Box* _cls, BoxedTuple* args, BoxedDict* kwargs) {
...@@ -596,6 +628,9 @@ void setupDict() { ...@@ -596,6 +628,9 @@ void setupDict() {
dict_cls->giveAttr("__init__", new BoxedFunction(boxRTFunction((void*)dictInit, NONE, 1, 0, true, true))); dict_cls->giveAttr("__init__", new BoxedFunction(boxRTFunction((void*)dictInit, NONE, 1, 0, true, true)));
dict_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)dictRepr, STR, 1))); dict_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)dictRepr, STR, 1)));
dict_cls->giveAttr("__eq__", new BoxedFunction(boxRTFunction((void*)dictEq, BOXED_BOOL, 2)));
dict_cls->giveAttr("__ne__", new BoxedFunction(boxRTFunction((void*)dictNe, BOXED_BOOL, 2)));
dict_cls->giveAttr("__iter__", dict_cls->giveAttr("__iter__",
new BoxedFunction(boxRTFunction((void*)dictIterKeys, typeFromClass(dict_iterator_cls), 1))); new BoxedFunction(boxRTFunction((void*)dictIterKeys, typeFromClass(dict_iterator_cls), 1)));
......
...@@ -597,7 +597,13 @@ BoxedFloat* _floatNew(Box* a) { ...@@ -597,7 +597,13 @@ BoxedFloat* _floatNew(Box* a) {
if (s == "-inf") if (s == "-inf")
return new BoxedFloat(-INFINITY); return new BoxedFloat(-INFINITY);
return new BoxedFloat(strtod(s.c_str(), NULL)); // TODO this should just use CPython's implementation:
char* endptr;
const char* startptr = s.c_str();
double r = strtod(startptr, &endptr);
if (endptr != startptr + s.size())
raiseExcHelper(ValueError, "could not convert string to float: %s", s.c_str());
return new BoxedFloat(r);
} else { } else {
static const std::string float_str("__float__"); static const std::string float_str("__float__");
Box* r = callattr(a, &float_str, CallattrFlags({.cls_only = true, .null_on_nonexistent = true }), Box* r = callattr(a, &float_str, CallattrFlags({.cls_only = true, .null_on_nonexistent = true }),
......
...@@ -1651,6 +1651,51 @@ bool dataDescriptorSetSpecialCases(Box* obj, Box* val, Box* descr, SetattrRewrit ...@@ -1651,6 +1651,51 @@ bool dataDescriptorSetSpecialCases(Box* obj, Box* val, Box* descr, SetattrRewrit
void setattrInternal(Box* obj, const std::string& attr, Box* val, SetattrRewriteArgs* rewrite_args) { void setattrInternal(Box* obj, const std::string& attr, Box* val, SetattrRewriteArgs* rewrite_args) {
assert(gc::isValidGCObject(val)); assert(gc::isValidGCObject(val));
if (obj->cls == type_cls) {
BoxedClass* cobj = static_cast<BoxedClass*>(obj);
if (!isUserDefined(cobj)) {
raiseExcHelper(TypeError, "can't set attributes of built-in/extension type '%s'", getNameOfClass(cobj));
}
}
if (attr == "__class__") {
if (!isSubclass(val->cls, type_cls))
raiseExcHelper(TypeError, "__class__ must be set to new-style class, not '%s' object", val->cls->tp_name);
auto new_cls = static_cast<BoxedClass*>(val);
// Conservative Pyston checks: make sure that both classes are derived only from Pyston types,
// and that they don't define any extra C-level fields
RELEASE_ASSERT(val->cls == type_cls, "");
RELEASE_ASSERT(obj->cls->cls == type_cls, "");
for (auto _base : static_cast<BoxedTuple*>(obj->cls->tp_mro)->elts) {
BoxedClass* base = static_cast<BoxedClass*>(_base);
RELEASE_ASSERT(base->is_pyston_class, "");
}
for (auto _base : static_cast<BoxedTuple*>(new_cls->tp_mro)->elts) {
BoxedClass* base = static_cast<BoxedClass*>(_base);
RELEASE_ASSERT(base->is_pyston_class, "");
}
RELEASE_ASSERT(obj->cls->tp_basicsize == object_cls->tp_basicsize + sizeof(HCAttrs) + sizeof(Box**), "");
RELEASE_ASSERT(new_cls->tp_basicsize == object_cls->tp_basicsize + sizeof(HCAttrs) + sizeof(Box**), "");
RELEASE_ASSERT(obj->cls->attrs_offset != 0, "");
RELEASE_ASSERT(new_cls->attrs_offset != 0, "");
RELEASE_ASSERT(obj->cls->tp_weaklistoffset != 0, "");
RELEASE_ASSERT(new_cls->tp_weaklistoffset != 0, "");
// Normal Python checks.
// TODO there are more checks to add here, and they should throw errors not asserts
RELEASE_ASSERT(obj->cls->tp_basicsize == new_cls->tp_basicsize, "");
RELEASE_ASSERT(obj->cls->tp_dictoffset == new_cls->tp_dictoffset, "");
RELEASE_ASSERT(obj->cls->tp_weaklistoffset == new_cls->tp_weaklistoffset, "");
RELEASE_ASSERT(obj->cls->attrs_offset == new_cls->attrs_offset, "");
obj->cls = new_cls;
return;
}
// Lookup a descriptor // Lookup a descriptor
Box* descr = NULL; Box* descr = NULL;
RewriterVar* r_descr = NULL; RewriterVar* r_descr = NULL;
...@@ -1744,18 +1789,9 @@ void setattrInternal(Box* obj, const std::string& attr, Box* val, SetattrRewrite ...@@ -1744,18 +1789,9 @@ void setattrInternal(Box* obj, const std::string& attr, Box* val, SetattrRewrite
} }
extern "C" void setattr(Box* obj, const char* attr, Box* attr_val) { extern "C" void setattr(Box* obj, const char* attr, Box* attr_val) {
assert(strcmp(attr, "__class__") != 0);
static StatCounter slowpath_setattr("slowpath_setattr"); static StatCounter slowpath_setattr("slowpath_setattr");
slowpath_setattr.log(); slowpath_setattr.log();
if (obj->cls == type_cls) {
BoxedClass* cobj = static_cast<BoxedClass*>(obj);
if (!isUserDefined(cobj)) {
raiseExcHelper(TypeError, "can't set attributes of built-in/extension type '%s'", getNameOfClass(cobj));
}
}
std::unique_ptr<Rewriter> rewriter( std::unique_ptr<Rewriter> rewriter(
Rewriter::createRewriter(__builtin_extract_return_addr(__builtin_return_address(0)), 3, "setattr")); Rewriter::createRewriter(__builtin_extract_return_addr(__builtin_return_address(0)), 3, "setattr"));
...@@ -2433,17 +2469,21 @@ static CompiledFunction* pickVersion(CLFunction* f, int num_output_args, Box* oa ...@@ -2433,17 +2469,21 @@ static CompiledFunction* pickVersion(CLFunction* f, int num_output_args, Box* oa
abort(); abort();
} }
EffortLevel new_effort = initialEffort();
std::vector<ConcreteCompilerType*> arg_types; std::vector<ConcreteCompilerType*> arg_types;
for (int i = 0; i < num_output_args; i++) { for (int i = 0; i < num_output_args; i++) {
if (new_effort == EffortLevel::INTERPRETED) {
arg_types.push_back(UNKNOWN);
} else {
Box* arg = getArg(i, oarg1, oarg2, oarg3, oargs); Box* arg = getArg(i, oarg1, oarg2, oarg3, oargs);
assert(arg); // only builtin functions can pass NULL args assert(arg); // only builtin functions can pass NULL args
arg_types.push_back(typeFromClass(arg->cls)); arg_types.push_back(typeFromClass(arg->cls));
} }
}
FunctionSpecialization* spec = new FunctionSpecialization(UNKNOWN, arg_types); FunctionSpecialization* spec = new FunctionSpecialization(UNKNOWN, arg_types);
EffortLevel new_effort = initialEffort();
// this also pushes the new CompiledVersion to the back of the version list: // this also pushes the new CompiledVersion to the back of the version list:
chosen_cf = compileFunction(f, spec, new_effort, NULL); chosen_cf = compileFunction(f, spec, new_effort, NULL);
} }
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "runtime/types.h" #include "runtime/types.h"
#include "runtime/util.h" #include "runtime/util.h"
extern "C" PyObject* string_split(PyStringObject* self, PyObject* args) noexcept;
extern "C" PyObject* string_rsplit(PyStringObject* self, PyObject* args) noexcept; extern "C" PyObject* string_rsplit(PyStringObject* self, PyObject* args) noexcept;
extern "C" PyObject* string_find(PyStringObject* self, PyObject* args) noexcept; extern "C" PyObject* string_find(PyStringObject* self, PyObject* args) noexcept;
extern "C" PyObject* string_rfind(PyStringObject* self, PyObject* args) noexcept; extern "C" PyObject* string_rfind(PyStringObject* self, PyObject* args) noexcept;
...@@ -1589,22 +1590,19 @@ Box* strIsUpper(BoxedString* self) { ...@@ -1589,22 +1590,19 @@ Box* strIsUpper(BoxedString* self) {
assert(isSubclass(self->cls, str_cls)); assert(isSubclass(self->cls, str_cls));
const std::string& str(self->s); const std::string& str(self->s);
bool uppered = false;
if (str.empty()) if (str.empty())
return False; return False;
bool cased = false;
for (const auto& c : str) { for (const auto& c : str) {
if (std::isspace(c) || std::isdigit(c)) { if (std::islower(c))
continue;
} else if (!std::isupper(c)) {
return False; return False;
} else { else if (!cased && isupper(c))
uppered = true; cased = true;
}
} }
return boxBool(uppered); return boxBool(cased);
} }
Box* strIsSpace(BoxedString* self) { Box* strIsSpace(BoxedString* self) {
...@@ -1734,6 +1732,21 @@ Box* strPartition(BoxedString* self, BoxedString* sep) { ...@@ -1734,6 +1732,21 @@ Box* strPartition(BoxedString* self, BoxedString* sep) {
self->s.size() - found_idx - sep->s.size()) }); self->s.size() - found_idx - sep->s.size()) });
} }
Box* strRpartition(BoxedString* self, BoxedString* sep) {
RELEASE_ASSERT(isSubclass(self->cls, str_cls), "");
RELEASE_ASSERT(isSubclass(sep->cls, str_cls), "");
size_t found_idx = self->s.rfind(sep->s);
if (found_idx == std::string::npos)
return new BoxedTuple({ self, boxStrConstant(""), boxStrConstant("") });
return new BoxedTuple({ boxStrConstantSize(self->s.c_str(), found_idx),
boxStrConstantSize(self->s.c_str() + found_idx, sep->s.size()),
boxStrConstantSize(self->s.c_str() + found_idx + sep->s.size(),
self->s.size() - found_idx - sep->s.size()) });
}
extern "C" PyObject* _do_string_format(PyObject* self, PyObject* args, PyObject* kwargs); extern "C" PyObject* _do_string_format(PyObject* self, PyObject* args, PyObject* kwargs);
Box* strFormat(BoxedString* self, BoxedTuple* args, BoxedDict* kwargs) { Box* strFormat(BoxedString* self, BoxedTuple* args, BoxedDict* kwargs) {
...@@ -1746,47 +1759,6 @@ Box* strFormat(BoxedString* self, BoxedTuple* args, BoxedDict* kwargs) { ...@@ -1746,47 +1759,6 @@ Box* strFormat(BoxedString* self, BoxedTuple* args, BoxedDict* kwargs) {
return rtn; return rtn;
} }
Box* strSplit(BoxedString* self, BoxedString* sep, BoxedInt* _max_split) {
assert(isSubclass(self->cls, str_cls));
if (_max_split->cls != int_cls)
raiseExcHelper(TypeError, "an integer is required");
if (isSubclass(sep->cls, str_cls)) {
if (!sep->s.empty()) {
llvm::SmallVector<llvm::StringRef, 16> parts;
llvm::StringRef(self->s).split(parts, sep->s, _max_split->n);
BoxedList* rtn = new BoxedList();
for (const auto& s : parts)
listAppendInternal(rtn, boxString(s.str()));
return rtn;
} else {
raiseExcHelper(ValueError, "empty separator");
}
} else if (sep->cls == none_cls) {
RELEASE_ASSERT(_max_split->n < 0, "this case hasn't been updated to handle limited splitting amounts");
BoxedList* rtn = new BoxedList();
std::ostringstream os("");
for (char c : self->s) {
if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v') {
if (os.tellp()) {
listAppendInternal(rtn, boxString(os.str()));
os.str("");
}
} else {
os << c;
}
}
if (os.tellp()) {
listAppendInternal(rtn, boxString(os.str()));
}
return rtn;
} else {
raiseExcHelper(TypeError, "expected a character buffer object");
}
}
Box* strStrip(BoxedString* self, Box* chars) { Box* strStrip(BoxedString* self, Box* chars) {
assert(isSubclass(self->cls, str_cls)); assert(isSubclass(self->cls, str_cls));
...@@ -2070,9 +2042,15 @@ Box* strDecode(BoxedString* self, Box* encoding, Box* error) { ...@@ -2070,9 +2042,15 @@ Box* strDecode(BoxedString* self, Box* encoding, Box* error) {
BoxedString* encoding_str = (BoxedString*)encoding; BoxedString* encoding_str = (BoxedString*)encoding;
BoxedString* error_str = (BoxedString*)error; BoxedString* error_str = (BoxedString*)error;
if (encoding_str && encoding_str->cls == unicode_cls)
encoding_str = (BoxedString*)_PyUnicode_AsDefaultEncodedString(encoding_str, NULL);
if (encoding_str && encoding_str->cls != str_cls) if (encoding_str && encoding_str->cls != str_cls)
raiseExcHelper(TypeError, "decode() argument 1 must be string, not '%s'", getTypeName(encoding_str)); raiseExcHelper(TypeError, "decode() argument 1 must be string, not '%s'", getTypeName(encoding_str));
if (error_str && error_str->cls == unicode_cls)
error_str = (BoxedString*)_PyUnicode_AsDefaultEncodedString(error_str, NULL);
if (error_str && error_str->cls != str_cls) if (error_str && error_str->cls != str_cls)
raiseExcHelper(TypeError, "decode() argument 2 must be string, not '%s'", getTypeName(error_str)); raiseExcHelper(TypeError, "decode() argument 2 must be string, not '%s'", getTypeName(error_str));
...@@ -2089,9 +2067,15 @@ Box* strEncode(BoxedString* self, Box* encoding, Box* error) { ...@@ -2089,9 +2067,15 @@ Box* strEncode(BoxedString* self, Box* encoding, Box* error) {
BoxedString* encoding_str = (BoxedString*)encoding; BoxedString* encoding_str = (BoxedString*)encoding;
BoxedString* error_str = (BoxedString*)error; BoxedString* error_str = (BoxedString*)error;
if (encoding_str && encoding_str->cls == unicode_cls)
encoding_str = (BoxedString*)_PyUnicode_AsDefaultEncodedString(encoding_str, NULL);
if (encoding_str && encoding_str->cls != str_cls) if (encoding_str && encoding_str->cls != str_cls)
raiseExcHelper(TypeError, "encode() argument 1 must be string, not '%s'", getTypeName(encoding_str)); raiseExcHelper(TypeError, "encode() argument 1 must be string, not '%s'", getTypeName(encoding_str));
if (error_str && error_str->cls == unicode_cls)
error_str = (BoxedString*)_PyUnicode_AsDefaultEncodedString(error_str, NULL);
if (error_str && error_str->cls != str_cls) if (error_str && error_str->cls != str_cls)
raiseExcHelper(TypeError, "encode() argument 2 must be string, not '%s'", getTypeName(error_str)); raiseExcHelper(TypeError, "encode() argument 2 must be string, not '%s'", getTypeName(error_str));
...@@ -2449,6 +2433,7 @@ void strDestructor(Box* b) { ...@@ -2449,6 +2433,7 @@ void strDestructor(Box* b) {
} }
static PyMethodDef string_methods[] = { static PyMethodDef string_methods[] = {
{ "split", (PyCFunction)string_split, METH_VARARGS, NULL },
{ "rsplit", (PyCFunction)string_rsplit, METH_VARARGS, NULL }, { "rsplit", (PyCFunction)string_rsplit, METH_VARARGS, NULL },
{ "find", (PyCFunction)string_find, METH_VARARGS, NULL }, { "find", (PyCFunction)string_find, METH_VARARGS, NULL },
{ "rfind", (PyCFunction)string_rfind, METH_VARARGS, NULL }, { "rfind", (PyCFunction)string_rfind, METH_VARARGS, NULL },
...@@ -2509,6 +2494,7 @@ void setupStr() { ...@@ -2509,6 +2494,7 @@ void setupStr() {
new BoxedFunction(boxRTFunction((void*)strEndswith, BOXED_BOOL, 4, 2, 0, 0), { NULL, NULL })); new BoxedFunction(boxRTFunction((void*)strEndswith, BOXED_BOOL, 4, 2, 0, 0), { NULL, NULL }));
str_cls->giveAttr("partition", new BoxedFunction(boxRTFunction((void*)strPartition, UNKNOWN, 2))); str_cls->giveAttr("partition", new BoxedFunction(boxRTFunction((void*)strPartition, UNKNOWN, 2)));
str_cls->giveAttr("rpartition", new BoxedFunction(boxRTFunction((void*)strRpartition, UNKNOWN, 2)));
str_cls->giveAttr("format", new BoxedFunction(boxRTFunction((void*)strFormat, UNKNOWN, 1, 0, true, true))); str_cls->giveAttr("format", new BoxedFunction(boxRTFunction((void*)strFormat, UNKNOWN, 1, 0, true, true)));
...@@ -2542,9 +2528,6 @@ void setupStr() { ...@@ -2542,9 +2528,6 @@ void setupStr() {
str_cls->giveAttr("replace", str_cls->giveAttr("replace",
new BoxedFunction(boxRTFunction((void*)strReplace, UNKNOWN, 4, 1, false, false), { boxInt(-1) })); new BoxedFunction(boxRTFunction((void*)strReplace, UNKNOWN, 4, 1, false, false), { boxInt(-1) }));
str_cls->giveAttr(
"split", new BoxedFunction(boxRTFunction((void*)strSplit, LIST, 3, 2, false, false), { None, boxInt(-1) }));
for (auto& md : string_methods) { for (auto& md : string_methods) {
str_cls->giveAttr(md.ml_name, new BoxedMethodDescriptor(&md, str_cls)); str_cls->giveAttr(md.ml_name, new BoxedMethodDescriptor(&md, str_cls));
} }
......
...@@ -561,7 +561,7 @@ BoxedClass* object_cls, *type_cls, *none_cls, *bool_cls, *int_cls, *float_cls, ...@@ -561,7 +561,7 @@ BoxedClass* object_cls, *type_cls, *none_cls, *bool_cls, *int_cls, *float_cls,
* str_cls = NULL, *function_cls, *instancemethod_cls, *list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls, * str_cls = NULL, *function_cls, *instancemethod_cls, *list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls,
*file_cls, *member_cls, *closure_cls, *generator_cls, *complex_cls, *basestring_cls, *property_cls, *file_cls, *member_cls, *closure_cls, *generator_cls, *complex_cls, *basestring_cls, *property_cls,
*staticmethod_cls, *classmethod_cls, *attrwrapper_cls, *pyston_getset_cls, *capi_getset_cls, *staticmethod_cls, *classmethod_cls, *attrwrapper_cls, *pyston_getset_cls, *capi_getset_cls,
*builtin_function_or_method_cls; *builtin_function_or_method_cls, *attrwrapperiter_cls;
BoxedTuple* EmptyTuple; BoxedTuple* EmptyTuple;
} }
...@@ -596,24 +596,25 @@ extern "C" Box* createUserClass(const std::string* name, Box* _bases, Box* _attr ...@@ -596,24 +596,25 @@ extern "C" Box* createUserClass(const std::string* name, Box* _bases, Box* _attr
RELEASE_ASSERT(r, ""); RELEASE_ASSERT(r, "");
return r; return r;
} catch (ExcInfo e) { } catch (ExcInfo e) {
// TODO [CAPI] bad error handling...
RELEASE_ASSERT(e.matches(BaseException), ""); RELEASE_ASSERT(e.matches(BaseException), "");
Box* msg = getattr(e.value, "message"); Box* msg = e.value;
RELEASE_ASSERT(msg, ""); assert(msg);
RELEASE_ASSERT(msg->cls == str_cls, ""); // TODO this is an extra Pyston check and I don't think we should have to do it:
if (isSubclass(e.value->cls, BaseException))
msg = getattr(e.value, "message");
PyObject* newmsg; if (isSubclass(msg->cls, str_cls)) {
newmsg = PyString_FromFormat("Error when calling the metaclass bases\n" auto newmsg = PyString_FromFormat("Error when calling the metaclass bases\n"
" %s", " %s",
PyString_AS_STRING(msg)); PyString_AS_STRING(msg));
if (newmsg)
e.value = newmsg;
}
PyErr_Restore(e.type, newmsg, NULL); // Go through these routines since they do some normalization:
checkAndThrowCAPIException(); PyErr_Restore(e.type, e.value, NULL);
throwCAPIException();
// Should not reach here
abort();
} }
} }
...@@ -955,6 +956,30 @@ CLFunction* unboxRTFunction(Box* b) { ...@@ -955,6 +956,30 @@ CLFunction* unboxRTFunction(Box* b) {
return static_cast<BoxedFunction*>(b)->f; return static_cast<BoxedFunction*>(b)->f;
} }
class AttrWrapper;
class AttrWrapperIter : public Box {
private:
// Iterating over the an attrwrapper (~=dict) just gives the keys, which
// just depends on the hidden class of the object. Let's store only that:
HiddenClass* hcls;
std::unordered_map<std::string, int>::iterator it;
public:
AttrWrapperIter(AttrWrapper* aw);
DEFAULT_CLASS(attrwrapperiter_cls);
static void gcHandler(GCVisitor* v, Box* b) {
boxGCHandler(v, b);
AttrWrapperIter* self = (AttrWrapperIter*)b;
v->visit(self->hcls);
}
static Box* hasnext(Box* _self);
static Box* next(Box* _self);
};
// A dictionary-like wrapper around the attributes array. // A dictionary-like wrapper around the attributes array.
// Not sure if this will be enough to satisfy users who expect __dict__ // Not sure if this will be enough to satisfy users who expect __dict__
// or PyModule_GetDict to return real dicts. // or PyModule_GetDict to return real dicts.
...@@ -1006,7 +1031,7 @@ public: ...@@ -1006,7 +1031,7 @@ public:
_key = coerceUnicodeToStr(_key); _key = coerceUnicodeToStr(_key);
RELEASE_ASSERT(_key->cls == str_cls, ""); RELEASE_ASSERT(_key->cls == str_cls, "%s", _key->cls->tp_name);
BoxedString* key = static_cast<BoxedString*>(_key); BoxedString* key = static_cast<BoxedString*>(_key);
Box* r = self->b->getattr(key->s); Box* r = self->b->getattr(key->s);
if (!r) if (!r)
...@@ -1087,6 +1112,19 @@ public: ...@@ -1087,6 +1112,19 @@ public:
return rtn; return rtn;
} }
static Box* copy(Box* _self) {
RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
AttrWrapper* self = static_cast<AttrWrapper*>(_self);
BoxedDict* rtn = new BoxedDict();
HCAttrs* attrs = self->b->getHCAttrsPtr();
for (const auto& p : attrs->hcls->attr_offsets) {
rtn->d[boxString(p.first)] = attrs->attr_list->attrs[p.second];
}
return rtn;
}
static Box* len(Box* _self) { static Box* len(Box* _self) {
RELEASE_ASSERT(_self->cls == attrwrapper_cls, ""); RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
AttrWrapper* self = static_cast<AttrWrapper*>(_self); AttrWrapper* self = static_cast<AttrWrapper*>(_self);
...@@ -1111,8 +1149,40 @@ public: ...@@ -1111,8 +1149,40 @@ public:
} }
return None; return None;
} }
static Box* iter(Box* _self) {
RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
AttrWrapper* self = static_cast<AttrWrapper*>(_self);
return new AttrWrapperIter(self);
}
friend class AttrWrapperIter;
}; };
AttrWrapperIter::AttrWrapperIter(AttrWrapper* aw) {
hcls = aw->b->getHCAttrsPtr()->hcls;
assert(hcls);
it = hcls->attr_offsets.begin();
}
Box* AttrWrapperIter::hasnext(Box* _self) {
RELEASE_ASSERT(_self->cls == attrwrapperiter_cls, "");
AttrWrapperIter* self = static_cast<AttrWrapperIter*>(_self);
return boxBool(self->it != self->hcls->attr_offsets.end());
}
Box* AttrWrapperIter::next(Box* _self) {
RELEASE_ASSERT(_self->cls == attrwrapperiter_cls, "");
AttrWrapperIter* self = static_cast<AttrWrapperIter*>(_self);
assert(self->it != self->hcls->attr_offsets.end());
Box* r = boxString(self->it->first);
++self->it;
return r;
}
Box* makeAttrWrapper(Box* b) { Box* makeAttrWrapper(Box* b) {
assert(b->cls->instancesHaveHCAttrs()); assert(b->cls->instancesHaveHCAttrs());
return new AttrWrapper(b); return new AttrWrapper(b);
...@@ -1378,6 +1448,8 @@ void setupRuntime() { ...@@ -1378,6 +1448,8 @@ void setupRuntime() {
sizeof(BoxedClassmethod), false, "classmethod"); sizeof(BoxedClassmethod), false, "classmethod");
attrwrapper_cls = BoxedHeapClass::create(type_cls, object_cls, &AttrWrapper::gcHandler, 0, 0, sizeof(AttrWrapper), attrwrapper_cls = BoxedHeapClass::create(type_cls, object_cls, &AttrWrapper::gcHandler, 0, 0, sizeof(AttrWrapper),
false, "attrwrapper"); false, "attrwrapper");
attrwrapperiter_cls = BoxedHeapClass::create(type_cls, object_cls, &AttrWrapperIter::gcHandler, 0, 0,
sizeof(AttrWrapperIter), false, "attrwrapperiter");
// TODO: add explicit __get__ and __set__ methods to these // TODO: add explicit __get__ and __set__ methods to these
pyston_getset_cls->freeze(); pyston_getset_cls->freeze();
...@@ -1504,10 +1576,17 @@ void setupRuntime() { ...@@ -1504,10 +1576,17 @@ void setupRuntime() {
attrwrapper_cls->giveAttr("keys", new BoxedFunction(boxRTFunction((void*)AttrWrapper::keys, LIST, 1))); attrwrapper_cls->giveAttr("keys", new BoxedFunction(boxRTFunction((void*)AttrWrapper::keys, LIST, 1)));
attrwrapper_cls->giveAttr("values", new BoxedFunction(boxRTFunction((void*)AttrWrapper::values, LIST, 1))); attrwrapper_cls->giveAttr("values", new BoxedFunction(boxRTFunction((void*)AttrWrapper::values, LIST, 1)));
attrwrapper_cls->giveAttr("items", new BoxedFunction(boxRTFunction((void*)AttrWrapper::items, LIST, 1))); attrwrapper_cls->giveAttr("items", new BoxedFunction(boxRTFunction((void*)AttrWrapper::items, LIST, 1)));
attrwrapper_cls->giveAttr("copy", new BoxedFunction(boxRTFunction((void*)AttrWrapper::copy, UNKNOWN, 1)));
attrwrapper_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)AttrWrapper::len, BOXED_INT, 1))); attrwrapper_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)AttrWrapper::len, BOXED_INT, 1)));
attrwrapper_cls->giveAttr("__iter__", new BoxedFunction(boxRTFunction((void*)AttrWrapper::iter, UNKNOWN, 1)));
attrwrapper_cls->giveAttr("update", new BoxedFunction(boxRTFunction((void*)AttrWrapper::update, NONE, 2))); attrwrapper_cls->giveAttr("update", new BoxedFunction(boxRTFunction((void*)AttrWrapper::update, NONE, 2)));
attrwrapper_cls->freeze(); attrwrapper_cls->freeze();
attrwrapperiter_cls->giveAttr("__hasnext__",
new BoxedFunction(boxRTFunction((void*)AttrWrapperIter::hasnext, UNKNOWN, 1)));
attrwrapperiter_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)AttrWrapperIter::next, UNKNOWN, 1)));
attrwrapperiter_cls->freeze();
// sys is the first module that needs to be set up, due to modules // sys is the first module that needs to be set up, due to modules
// being tracked in sys.modules: // being tracked in sys.modules:
setupSys(); setupSys();
......
# expected: fail
# - class changing not supported yet
# Tests to make sure that setting __class__ changes the class, and that it's ok to disallow # Tests to make sure that setting __class__ changes the class, and that it's ok to disallow
# having anything other than a type as the class # having anything other than a type as the class
class C(object): class C(object):
...@@ -17,5 +14,7 @@ c.foo() ...@@ -17,5 +14,7 @@ c.foo()
c.__class__ = D c.__class__ = D
c.foo() c.foo()
# This should err: try:
c.__class__ = 1 c.__class__ = 1
except TypeError as e:
print e
...@@ -213,3 +213,11 @@ print list(d.viewvalues()) ...@@ -213,3 +213,11 @@ print list(d.viewvalues())
print list(d.viewitems()) print list(d.viewitems())
print 'keys of d: ', keys print 'keys of d: ', keys
print 'viewkeys of d: ', list(viewkeys) print 'viewkeys of d: ', list(viewkeys)
print {} == {}
d1 = {}
d2 = {}
for i in xrange(6):
d1[i] = 5 - i
d2[5 - i] = i
print d1 == d2, d1 != d2
...@@ -77,3 +77,17 @@ class C2(C1): ...@@ -77,3 +77,17 @@ class C2(C1):
b = 3 b = 3
c = 4 c = 4
print sorted([s for s in dir(C2) if s[0] != '_']) print sorted([s for s in dir(C2) if s[0] != '_'])
c = C1()
c.d = 2
d1 = c.__dict__
d2 = d1.copy()
c.e = 3
print sorted(d1.items())
print sorted(d2.items())
l = []
for x in d1:
l.append(x)
l.sort()
print l
...@@ -36,3 +36,17 @@ class F2(float): ...@@ -36,3 +36,17 @@ class F2(float):
print type(F2(D(F()))) print type(F2(D(F())))
print type(float(F())) print type(float(F()))
try:
f = float("hello world")
print f
except ValueError as e:
print e
try:
f = float("5 hello world")
print f
except ValueError as e:
pass
# We don't print the right thing yet:
# print e
...@@ -34,3 +34,12 @@ else: ...@@ -34,3 +34,12 @@ else:
for i in xrange(5): for i in xrange(5):
print i print i
break break
def f():
for i in xrange(5):
if i == 10:
return 2
else:
return 5
f()
...@@ -142,3 +142,6 @@ print repr("hello\tworld\t".expandtabs(12)) ...@@ -142,3 +142,6 @@ print repr("hello\tworld\t".expandtabs(12))
print "hello world".startswith(("x", "h")) print "hello world".startswith(("x", "h"))
print "hello world".endswith(("x", "h")) print "hello world".endswith(("x", "h"))
print "a.b.c.d".partition('.')
print "a.b.c.d".rpartition('.')
...@@ -93,6 +93,9 @@ for i in xrange(256): ...@@ -93,6 +93,9 @@ for i in xrange(256):
test(c) test(c)
test_is(c) test_is(c)
for j in xrange(i, 64):
test_is(c + chr(j))
try: try:
var = 'abc' var = 'abc'
var.isalnum(42) var.isalnum(42)
......
...@@ -37,6 +37,8 @@ print p(s.encode("utf8")) ...@@ -37,6 +37,8 @@ print p(s.encode("utf8"))
print p(s.encode("utf16")) print p(s.encode("utf16"))
print p(s.encode("utf32")) print p(s.encode("utf32"))
print p(s.encode("iso_8859_15")) print p(s.encode("iso_8859_15"))
print p(s.encode(u"utf8"))
print p("hello world".encode(u"utf8"))
print repr(u' '.join(["hello", "world"])) print repr(u' '.join(["hello", "world"]))
...@@ -91,3 +93,6 @@ print "hello world".startswith(u'world') ...@@ -91,3 +93,6 @@ print "hello world".startswith(u'world')
print float(u'1.0') print float(u'1.0')
print unichr(97) print unichr(97)
print "hello world".split(u'l')
print "hello world".rsplit(u'l')
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