Commit a262a1d1 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Implement filter(None, ...) and setattr()

parent 01fa0faf
......@@ -341,6 +341,16 @@ Box* getattrFunc(Box* obj, Box* _str, Box* default_value) {
return rtn;
}
Box* setattrFunc(Box* obj, Box* _str, Box* value) {
if (_str->cls != str_cls) {
raiseExcHelper(TypeError, "getattr(): attribute name must be string");
}
BoxedString* str = static_cast<BoxedString*>(_str);
setattrInternal(obj, str->s, value, NULL);
return None;
}
Box* hasattr(Box* obj, Box* _str) {
if (_str->cls != str_cls) {
raiseExcHelper(TypeError, "hasattr(): attribute name must be string");
......@@ -362,6 +372,14 @@ Box* map2(Box* f, Box* container) {
}
Box* filter2(Box* f, Box* container) {
// If the filter-function argument is None, filter() works by only returning
// the elements that are truthy. This is equivalent to using the bool() constructor.
// - actually since we call nonzero() afterwards, we could use an ident() function
// but we don't have one.
// If this is a common case we could speed it up with special handling.
if (f == None)
f = bool_cls;
Box* rtn = new BoxedList();
for (Box* e : container->pyElements()) {
Box* r = runtimeCall(f, ArgPassSpec(1), e, NULL, NULL, NULL, NULL);
......@@ -589,6 +607,9 @@ void setupBuiltins() {
builtins_module->giveAttr(
"getattr", new BoxedFunction(boxRTFunction((void*)getattrFunc, UNKNOWN, 3, 1, false, false), { NULL }));
builtins_module->giveAttr("setattr",
new BoxedFunction(boxRTFunction((void*)setattrFunc, UNKNOWN, 3, 0, false, false)));
Box* hasattr_obj = new BoxedFunction(boxRTFunction((void*)hasattr, BOXED_BOOL, 2));
builtins_module->giveAttr("hasattr", hasattr_obj);
......
......@@ -1340,7 +1340,7 @@ extern "C" Box* getattr(Box* obj, const char* attr) {
raiseAttributeError(obj, attr);
}
static void setattr_internal(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));
// Lookup a descriptor
......@@ -1431,7 +1431,7 @@ extern "C" void setattr(Box* obj, const char* attr, Box* attr_val) {
if (rewriter.get()) {
// rewriter->trap();
SetattrRewriteArgs rewrite_args(rewriter.get(), rewriter->getArg(0), rewriter->getArg(2), false);
setattr_internal(obj, attr, attr_val, &rewrite_args);
setattrInternal(obj, attr, attr_val, &rewrite_args);
if (rewrite_args.out_success) {
rewriter->commit();
} else {
......@@ -1439,7 +1439,7 @@ extern "C" void setattr(Box* obj, const char* attr, Box* attr_val) {
rewrite_args.attrval.ensureDoneUsing();
}
} else {
setattr_internal(obj, attr, attr_val, NULL);
setattrInternal(obj, attr, attr_val, NULL);
}
}
......
......@@ -85,6 +85,9 @@ extern "C" bool isSubclass(BoxedClass* child, BoxedClass* parent);
extern "C" BoxedClosure* createClosure(BoxedClosure* parent_closure);
extern "C" Box* getiter(Box* o);
class SetattrRewriteArgs;
void setattrInternal(Box* obj, const std::string& attr, Box* val, SetattrRewriteArgs* rewrite_args);
class BinopRewriteArgs;
extern "C" Box* binopInternal(Box* lhs, Box* rhs, int op_type, bool inplace, BinopRewriteArgs* rewrite_args);
......
......@@ -33,6 +33,9 @@ print filter(lambda x: x % 2, xrange(20))
print type(enumerate([]))
print list(enumerate(xrange(5, 10)))
# If the first argument is None, filter calls checks for truthiness (ie is equivalent to passing 'bool')
print filter(None, xrange(-5, 5))
print isinstance(1, int)
print isinstance(1, (float, int))
print isinstance(1, (float, (), (int, 3), 4))
......@@ -2,3 +2,16 @@ a = 'test'
assert hasattr(a, "__str__")
assert hasattr(a, "dupa") == False
class C(object):
pass
c = C()
assert not hasattr(c, "a")
c.a = 1
print getattr(c, "a")
assert hasattr(c, "a")
assert not hasattr(c, "b")
print setattr(c, "b", 5)
assert hasattr(c, "b")
print c.b
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