Commit dbac3625 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #292 from tjhance/set-function-name

implement setting __name__ for functions
parents efeaab75 4093d5a8
......@@ -11,19 +11,19 @@ print C
C.__module__ = 1
print C
def set_name(cls, name):
def set_name(obj, name):
try:
cls.__name__ = name
obj.__name__ = name
except Exception as e:
print type(e), e
print cls
print obj.__name__
def del_name(cls):
def del_name(obj):
try:
del cls.__name__
del obj.__name__
except Exception as e:
print type(e), e
print cls.__name__
print obj.__name__
set_name(int, "bob")
#TODO implement __del__ for getset descriptors
......@@ -32,3 +32,17 @@ set_name(int, "bob")
set_name(C, 5)
set_name(C, "b\0b")
set_name(C, "car")
def g():
pass
print g.__name__
set_name(g, "bob")
set_name(g, 5)
set_name(g, "b\0b")
f = lambda x : 5
print f.__name__
set_name(f, "bob")
set_name(f, 5)
set_name(f, "b\0b")
#del_name(f)
......@@ -271,7 +271,7 @@ void BoxIterator::gcHandler(GCVisitor* v) {
std::string builtinStr("__builtin__");
extern "C" BoxedFunctionBase::BoxedFunctionBase(CLFunction* f)
: f(f), closure(NULL), isGenerator(false), ndefaults(0), defaults(NULL) {
: f(f), closure(NULL), isGenerator(false), ndefaults(0), defaults(NULL), modname(NULL), name(NULL) {
if (f->source) {
this->modname = f->source->parent_module->getattr("__name__", NULL);
} else {
......@@ -285,7 +285,7 @@ extern "C" BoxedFunctionBase::BoxedFunctionBase(CLFunction* f)
extern "C" BoxedFunctionBase::BoxedFunctionBase(CLFunction* f, std::initializer_list<Box*> defaults,
BoxedClosure* closure, bool isGenerator)
: f(f), closure(closure), isGenerator(isGenerator), ndefaults(0), defaults(NULL) {
: f(f), closure(closure), isGenerator(isGenerator), ndefaults(0), defaults(NULL), modname(NULL), name(NULL) {
if (defaults.size()) {
// make sure to initialize defaults first, since the GC behavior is triggered by ndefaults,
// and a GC can happen within this constructor:
......@@ -305,10 +305,32 @@ extern "C" BoxedFunctionBase::BoxedFunctionBase(CLFunction* f, std::initializer_
assert(f->num_defaults == ndefaults);
}
BoxedFunction::BoxedFunction(CLFunction* f) : BoxedFunction(f, {}) {
}
BoxedFunction::BoxedFunction(CLFunction* f, std::initializer_list<Box*> defaults, BoxedClosure* closure,
bool isGenerator)
: BoxedFunctionBase(f, defaults, closure, isGenerator) {
// TODO eventually we want this to assert(f->source), I think, but there are still
// some builtin functions that are BoxedFunctions but really ought to be a type that
// we don't have yet.
if (f->source) {
this->name = static_cast<BoxedString*>(boxString(f->source->getName()));
}
}
extern "C" void functionGCHandler(GCVisitor* v, Box* b) {
boxGCHandler(v, b);
BoxedFunctionBase* f = (BoxedFunctionBase*)b;
BoxedFunction* f = (BoxedFunction*)b;
// TODO eventually f->name should always be non-NULL, then there'd be no need for this check
if (f->name)
v->visit(f->name);
if (f->modname)
v->visit(f->modname);
if (f->closure)
v->visit(f->closure);
......@@ -647,15 +669,19 @@ static Box* functionCall(BoxedFunction* self, Box* args, Box* kwargs) {
static Box* func_name(Box* b, void*) {
assert(b->cls == function_cls);
BoxedFunction* func = static_cast<BoxedFunction*>(b);
// TODO this isn't right
// (For one thing, we need to able to *set* the __name__ of a function, but that probably
// should not involve setting the name in the source.)
return boxString(func->f->source->getName());
RELEASE_ASSERT(func->name != NULL, "func->name is not set");
return func->name;
}
static void func_set_name(Box*, Box*, void*) {
RELEASE_ASSERT(0, "not implemented");
static void func_set_name(Box* b, Box* v, void*) {
assert(b->cls == function_cls);
BoxedFunction* func = static_cast<BoxedFunction*>(b);
if (v == NULL || !PyString_Check(v)) {
raiseExcHelper(TypeError, "__name__ must be set to a string object");
}
func->name = static_cast<BoxedString*>(v);
}
static Box* functionNonzero(BoxedFunction* self) {
......
......@@ -458,7 +458,8 @@ public:
ICInvalidator dependent_ics;
// Accessed via member descriptor
Box* modname; // __module__
Box* modname; // __module__
BoxedString* name; // __name__ (should be here or in one of the derived classes?)
BoxedFunctionBase(CLFunction* f);
BoxedFunctionBase(CLFunction* f, std::initializer_list<Box*> defaults, BoxedClosure* closure = NULL,
......@@ -467,10 +468,9 @@ public:
class BoxedFunction : public BoxedFunctionBase {
public:
BoxedFunction(CLFunction* f) : BoxedFunctionBase(f) {}
BoxedFunction(CLFunction* f);
BoxedFunction(CLFunction* f, std::initializer_list<Box*> defaults, BoxedClosure* closure = NULL,
bool isGenerator = false)
: BoxedFunctionBase(f, defaults, closure, isGenerator) {}
bool isGenerator = false);
DEFAULT_CLASS(function_cls);
};
......
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